15e96a66cSDavid du Colombier #include "stdinc.h" 25e96a66cSDavid du Colombier #include "dat.h" 35e96a66cSDavid du Colombier #include "fns.h" 45e96a66cSDavid du Colombier #include "error.h" 55e96a66cSDavid du Colombier 65e96a66cSDavid du Colombier /* 75e96a66cSDavid du Colombier * locking order is upwards. A thread can hold the lock for a File 85e96a66cSDavid du Colombier * and then acquire the lock of its parent 95e96a66cSDavid du Colombier */ 105e96a66cSDavid du Colombier 115e96a66cSDavid du Colombier struct File { 125e96a66cSDavid du Colombier Fs *fs; /* immutable */ 135e96a66cSDavid du Colombier 145e96a66cSDavid du Colombier /* meta data for file: protected by the lk in the parent */ 155e96a66cSDavid du Colombier int ref; /* holds this data structure up */ 165e96a66cSDavid du Colombier 175e96a66cSDavid du Colombier int partial; /* file was never really open */ 185e96a66cSDavid du Colombier int removed; /* file has been removed */ 195e96a66cSDavid du Colombier int dirty; /* dir is dirty with respect to meta data in block */ 205e96a66cSDavid du Colombier u32int boff; /* block offset within msource for this file's meta data */ 215e96a66cSDavid du Colombier 225e96a66cSDavid du Colombier DirEntry dir; /* meta data for this file */ 235e96a66cSDavid du Colombier 245e96a66cSDavid du Colombier File *up; /* parent file */ 255e96a66cSDavid du Colombier File *next; /* sibling */ 265e96a66cSDavid du Colombier 275e96a66cSDavid du Colombier /* data for file */ 285e96a66cSDavid du Colombier VtLock *lk; /* lock for the following */ 295e96a66cSDavid du Colombier Source *source; 305e96a66cSDavid du Colombier Source *msource; /* for directories: meta data for children */ 315e96a66cSDavid du Colombier File *down; /* children */ 325e96a66cSDavid du Colombier 335e96a66cSDavid du Colombier int mode; 345e96a66cSDavid du Colombier }; 355e96a66cSDavid du Colombier 365e96a66cSDavid du Colombier static int fileMetaFlush2(File*, char*); 375e96a66cSDavid du Colombier static u32int fileMetaAlloc(File*, DirEntry*, u32int); 385e96a66cSDavid du Colombier static int fileRLock(File*); 395e96a66cSDavid du Colombier static void fileRUnlock(File*); 405e96a66cSDavid du Colombier static int fileLock(File*); 415e96a66cSDavid du Colombier static void fileUnlock(File*); 425e96a66cSDavid du Colombier static void fileMetaLock(File*); 435e96a66cSDavid du Colombier static void fileMetaUnlock(File*); 445e96a66cSDavid du Colombier static void fileRAccess(File*); 455e96a66cSDavid du Colombier static void fileWAccess(File*, char*); 465e96a66cSDavid du Colombier 475e96a66cSDavid du Colombier static File * 485e96a66cSDavid du Colombier fileAlloc(Fs *fs) 495e96a66cSDavid du Colombier { 505e96a66cSDavid du Colombier File *f; 515e96a66cSDavid du Colombier 525e96a66cSDavid du Colombier f = vtMemAllocZ(sizeof(File)); 535e96a66cSDavid du Colombier f->lk = vtLockAlloc(); 545e96a66cSDavid du Colombier f->ref = 1; 555e96a66cSDavid du Colombier f->fs = fs; 565e96a66cSDavid du Colombier f->boff = NilBlock; 575e96a66cSDavid du Colombier f->mode = fs->mode; 585e96a66cSDavid du Colombier return f; 595e96a66cSDavid du Colombier } 605e96a66cSDavid du Colombier 615e96a66cSDavid du Colombier static void 625e96a66cSDavid du Colombier fileFree(File *f) 635e96a66cSDavid du Colombier { 645e96a66cSDavid du Colombier sourceClose(f->source); 655e96a66cSDavid du Colombier vtLockFree(f->lk); 665e96a66cSDavid du Colombier sourceClose(f->msource); 675e96a66cSDavid du Colombier deCleanup(&f->dir); 685e96a66cSDavid du Colombier 695e96a66cSDavid du Colombier memset(f, ~0, sizeof(File)); 705e96a66cSDavid du Colombier vtMemFree(f); 715e96a66cSDavid du Colombier } 725e96a66cSDavid du Colombier 735e96a66cSDavid du Colombier /* 745e96a66cSDavid du Colombier * the file is locked already 755e96a66cSDavid du Colombier * f->msource is unlocked 765e96a66cSDavid du Colombier */ 775e96a66cSDavid du Colombier static File * 785e96a66cSDavid du Colombier dirLookup(File *f, char *elem) 795e96a66cSDavid du Colombier { 805e96a66cSDavid du Colombier int i; 815e96a66cSDavid du Colombier MetaBlock mb; 825e96a66cSDavid du Colombier MetaEntry me; 835e96a66cSDavid du Colombier Block *b; 845e96a66cSDavid du Colombier Source *meta; 855e96a66cSDavid du Colombier File *ff; 865e96a66cSDavid du Colombier u32int bo, nb; 875e96a66cSDavid du Colombier 885e96a66cSDavid du Colombier meta = f->msource; 895e96a66cSDavid du Colombier b = nil; 905e96a66cSDavid du Colombier if(!sourceLock(meta, -1)) 915e96a66cSDavid du Colombier return nil; 925e96a66cSDavid du Colombier nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize; 935e96a66cSDavid du Colombier for(bo=0; bo<nb; bo++){ 945e96a66cSDavid du Colombier b = sourceBlock(meta, bo, OReadOnly); 955e96a66cSDavid du Colombier if(b == nil) 965e96a66cSDavid du Colombier goto Err; 975e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 985e96a66cSDavid du Colombier goto Err; 995e96a66cSDavid du Colombier if(mbSearch(&mb, elem, &i, &me)){ 1005e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 1015e96a66cSDavid du Colombier if(!deUnpack(&ff->dir, &me)){ 1025e96a66cSDavid du Colombier fileFree(ff); 1035e96a66cSDavid du Colombier goto Err; 1045e96a66cSDavid du Colombier } 1055e96a66cSDavid du Colombier sourceUnlock(meta); 1065e96a66cSDavid du Colombier blockPut(b); 1075e96a66cSDavid du Colombier ff->boff = bo; 1085e96a66cSDavid du Colombier ff->mode = f->mode; 1095e96a66cSDavid du Colombier return ff; 1105e96a66cSDavid du Colombier } 1115e96a66cSDavid du Colombier 1125e96a66cSDavid du Colombier blockPut(b); 1135e96a66cSDavid du Colombier b = nil; 1145e96a66cSDavid du Colombier } 1155e96a66cSDavid du Colombier vtSetError(ENoFile); 1165e96a66cSDavid du Colombier /* fall through */ 1175e96a66cSDavid du Colombier Err: 1185e96a66cSDavid du Colombier sourceUnlock(meta); 1195e96a66cSDavid du Colombier blockPut(b); 1205e96a66cSDavid du Colombier return nil; 1215e96a66cSDavid du Colombier } 1225e96a66cSDavid du Colombier 1235e96a66cSDavid du Colombier File * 1245e96a66cSDavid du Colombier fileRoot(Source *r) 1255e96a66cSDavid du Colombier { 1265e96a66cSDavid du Colombier Block *b; 1275e96a66cSDavid du Colombier Source *r0, *r1, *r2; 1285e96a66cSDavid du Colombier MetaBlock mb; 1295e96a66cSDavid du Colombier MetaEntry me; 1305e96a66cSDavid du Colombier File *root, *mr; 1315e96a66cSDavid du Colombier Fs *fs; 1325e96a66cSDavid du Colombier 1335e96a66cSDavid du Colombier b = nil; 1345e96a66cSDavid du Colombier root = nil; 1355e96a66cSDavid du Colombier mr = nil; 1365e96a66cSDavid du Colombier r1 = nil; 1375e96a66cSDavid du Colombier r2 = nil; 1385e96a66cSDavid du Colombier 1395e96a66cSDavid du Colombier fs = r->fs; 1405e96a66cSDavid du Colombier if(!sourceLock(r, -1)) 1415e96a66cSDavid du Colombier return nil; 1425e96a66cSDavid du Colombier r0 = sourceOpen(r, 0, fs->mode); 1435e96a66cSDavid du Colombier if(r0 == nil) 1445e96a66cSDavid du Colombier goto Err; 1455e96a66cSDavid du Colombier r1 = sourceOpen(r, 1, fs->mode); 1465e96a66cSDavid du Colombier if(r1 == nil) 1475e96a66cSDavid du Colombier goto Err; 1485e96a66cSDavid du Colombier r2 = sourceOpen(r, 2, fs->mode); 1495e96a66cSDavid du Colombier if(r2 == nil) 1505e96a66cSDavid du Colombier goto Err; 1515e96a66cSDavid du Colombier 1525e96a66cSDavid du Colombier mr = fileAlloc(fs); 1535e96a66cSDavid du Colombier mr->msource = r2; 1545e96a66cSDavid du Colombier r2 = nil; 1555e96a66cSDavid du Colombier 1565e96a66cSDavid du Colombier root = fileAlloc(fs); 1575e96a66cSDavid du Colombier root->boff = 0; 1585e96a66cSDavid du Colombier root->up = mr; 1595e96a66cSDavid du Colombier root->source = r0; 1605e96a66cSDavid du Colombier r0 = nil; 1615e96a66cSDavid du Colombier root->msource = r1; 1625e96a66cSDavid du Colombier r1 = nil; 1635e96a66cSDavid du Colombier 1645e96a66cSDavid du Colombier mr->down = root; 1655e96a66cSDavid du Colombier 1665e96a66cSDavid du Colombier if(!sourceLock(mr->msource, -1)) 1675e96a66cSDavid du Colombier goto Err; 1685e96a66cSDavid du Colombier b = sourceBlock(mr->msource, 0, OReadOnly); 1695e96a66cSDavid du Colombier sourceUnlock(mr->msource); 1705e96a66cSDavid du Colombier if(b == nil) 1715e96a66cSDavid du Colombier goto Err; 1725e96a66cSDavid du Colombier 1735e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, mr->msource->dsize)) 1745e96a66cSDavid du Colombier goto Err; 1755e96a66cSDavid du Colombier 1765e96a66cSDavid du Colombier meUnpack(&me, &mb, 0); 1775e96a66cSDavid du Colombier if(!deUnpack(&root->dir, &me)) 1785e96a66cSDavid du Colombier goto Err; 1795e96a66cSDavid du Colombier blockPut(b); 1805e96a66cSDavid du Colombier sourceUnlock(r); 1815e96a66cSDavid du Colombier fileRAccess(root); 1825e96a66cSDavid du Colombier 1835e96a66cSDavid du Colombier return root; 1845e96a66cSDavid du Colombier Err: 1855e96a66cSDavid du Colombier blockPut(b); 1865e96a66cSDavid du Colombier if(r0) 1875e96a66cSDavid du Colombier sourceClose(r0); 1885e96a66cSDavid du Colombier if(r1) 1895e96a66cSDavid du Colombier sourceClose(r1); 1905e96a66cSDavid du Colombier if(r2) 1915e96a66cSDavid du Colombier sourceClose(r2); 1925e96a66cSDavid du Colombier if(mr) 1935e96a66cSDavid du Colombier fileFree(mr); 1945e96a66cSDavid du Colombier if(root) 1955e96a66cSDavid du Colombier fileFree(root); 1965e96a66cSDavid du Colombier sourceUnlock(r); 1975e96a66cSDavid du Colombier 1985e96a66cSDavid du Colombier return nil; 1995e96a66cSDavid du Colombier } 2005e96a66cSDavid du Colombier 2015e96a66cSDavid du Colombier static Source * 2025e96a66cSDavid du Colombier fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode) 2035e96a66cSDavid du Colombier { 2045e96a66cSDavid du Colombier Source *r; 2055e96a66cSDavid du Colombier 2065e96a66cSDavid du Colombier if(!sourceLock(f->source, mode)) 2075e96a66cSDavid du Colombier return nil; 2085e96a66cSDavid du Colombier r = sourceOpen(f->source, offset, mode); 2095e96a66cSDavid du Colombier sourceUnlock(f->source); 2105e96a66cSDavid du Colombier if(r == nil) 2115e96a66cSDavid du Colombier return nil; 2125e96a66cSDavid du Colombier if(r->gen != gen){ 2135e96a66cSDavid du Colombier vtSetError(ERemoved); 2145e96a66cSDavid du Colombier goto Err; 2155e96a66cSDavid du Colombier } 2165e96a66cSDavid du Colombier if(r->dir != dir && r->mode != -1){ 2175e96a66cSDavid du Colombier fprint(2, "fileOpenSource: dir mismatch %d %d\n", r->dir, dir); 2185e96a66cSDavid du Colombier vtSetError(EBadMeta); 2195e96a66cSDavid du Colombier goto Err; 2205e96a66cSDavid du Colombier } 2215e96a66cSDavid du Colombier return r; 2225e96a66cSDavid du Colombier Err: 2235e96a66cSDavid du Colombier sourceClose(r); 2245e96a66cSDavid du Colombier return nil; 2255e96a66cSDavid du Colombier } 2265e96a66cSDavid du Colombier 2275e96a66cSDavid du Colombier File * 2285e96a66cSDavid du Colombier _fileWalk(File *f, char *elem, int partial) 2295e96a66cSDavid du Colombier { 2305e96a66cSDavid du Colombier File *ff; 2315e96a66cSDavid du Colombier 2325e96a66cSDavid du Colombier fileRAccess(f); 2335e96a66cSDavid du Colombier 2345e96a66cSDavid du Colombier if(elem[0] == 0){ 2355e96a66cSDavid du Colombier vtSetError(EBadPath); 2365e96a66cSDavid du Colombier return nil; 2375e96a66cSDavid du Colombier } 2385e96a66cSDavid du Colombier 2395e96a66cSDavid du Colombier if(!fileIsDir(f)){ 2405e96a66cSDavid du Colombier vtSetError(ENotDir); 2415e96a66cSDavid du Colombier return nil; 2425e96a66cSDavid du Colombier } 2435e96a66cSDavid du Colombier 2445e96a66cSDavid du Colombier if(strcmp(elem, ".") == 0){ 2455e96a66cSDavid du Colombier return fileIncRef(f); 2465e96a66cSDavid du Colombier } 2475e96a66cSDavid du Colombier 2485e96a66cSDavid du Colombier if(strcmp(elem, "..") == 0){ 2495e96a66cSDavid du Colombier if(fileIsRoot(f)) 2505e96a66cSDavid du Colombier return fileIncRef(f); 2515e96a66cSDavid du Colombier return fileIncRef(f->up); 2525e96a66cSDavid du Colombier } 2535e96a66cSDavid du Colombier 2545e96a66cSDavid du Colombier if(!fileLock(f)) 2555e96a66cSDavid du Colombier return nil; 2565e96a66cSDavid du Colombier 2575e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 2585e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 2595e96a66cSDavid du Colombier ff->ref++; 2605e96a66cSDavid du Colombier goto Exit; 2615e96a66cSDavid du Colombier } 2625e96a66cSDavid du Colombier } 2635e96a66cSDavid du Colombier 2645e96a66cSDavid du Colombier ff = dirLookup(f, elem); 2655e96a66cSDavid du Colombier if(ff == nil) 2665e96a66cSDavid du Colombier goto Err; 2675e96a66cSDavid du Colombier 2685e96a66cSDavid du Colombier if(ff->dir.mode & ModeSnapshot) 2695e96a66cSDavid du Colombier ff->mode = OReadOnly; 2705e96a66cSDavid du Colombier 2715e96a66cSDavid du Colombier if(partial){ 2725e96a66cSDavid du Colombier /* 2735e96a66cSDavid du Colombier * Do nothing. We're opening this file only so we can clri it. 2745e96a66cSDavid du Colombier * Usually the sources can't be opened, hence we won't even bother. 2755e96a66cSDavid du Colombier * Be VERY careful with the returned file. If you hand it to a routine 2765e96a66cSDavid du Colombier * expecting ff->source and/or ff->msource to be non-nil, we're 2775e96a66cSDavid du Colombier * likely to dereference nil. FileClri should be the only routine 2785e96a66cSDavid du Colombier * setting partial. 2795e96a66cSDavid du Colombier */ 2805e96a66cSDavid du Colombier ff->partial = 1; 2815e96a66cSDavid du Colombier }else if(ff->dir.mode & ModeDir){ 2825e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode); 2835e96a66cSDavid du Colombier ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode); 2845e96a66cSDavid du Colombier if(ff->source == nil || ff->msource == nil) 2855e96a66cSDavid du Colombier goto Err; 2865e96a66cSDavid du Colombier }else{ 2875e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode); 2885e96a66cSDavid du Colombier if(ff->source == nil) 2895e96a66cSDavid du Colombier goto Err; 2905e96a66cSDavid du Colombier } 2915e96a66cSDavid du Colombier 2925e96a66cSDavid du Colombier /* link in and up parent ref count */ 2935e96a66cSDavid du Colombier ff->next = f->down; 2945e96a66cSDavid du Colombier f->down = ff; 2955e96a66cSDavid du Colombier ff->up = f; 2965e96a66cSDavid du Colombier fileIncRef(f); 2975e96a66cSDavid du Colombier Exit: 2985e96a66cSDavid du Colombier fileUnlock(f); 2995e96a66cSDavid du Colombier return ff; 3005e96a66cSDavid du Colombier Err: 3015e96a66cSDavid du Colombier fileUnlock(f); 3025e96a66cSDavid du Colombier if(ff != nil) 3035e96a66cSDavid du Colombier fileDecRef(ff); 3045e96a66cSDavid du Colombier return nil; 3055e96a66cSDavid du Colombier } 3065e96a66cSDavid du Colombier 3075e96a66cSDavid du Colombier File * 3085e96a66cSDavid du Colombier fileWalk(File *f, char *elem) 3095e96a66cSDavid du Colombier { 3105e96a66cSDavid du Colombier return _fileWalk(f, elem, 0); 3115e96a66cSDavid du Colombier } 3125e96a66cSDavid du Colombier 3135e96a66cSDavid du Colombier File * 3145e96a66cSDavid du Colombier _fileOpen(Fs *fs, char *path, int partial) 3155e96a66cSDavid du Colombier { 3165e96a66cSDavid du Colombier File *f, *ff; 317f8e525acSDavid du Colombier char *p, elem[VtMaxStringSize], *opath; 3185e96a66cSDavid du Colombier int n; 3195e96a66cSDavid du Colombier 3205e96a66cSDavid du Colombier f = fs->file; 3215e96a66cSDavid du Colombier fileIncRef(f); 322f8e525acSDavid du Colombier opath = path; 3235e96a66cSDavid du Colombier while(*path != 0){ 3245e96a66cSDavid du Colombier for(p = path; *p && *p != '/'; p++) 3255e96a66cSDavid du Colombier ; 3265e96a66cSDavid du Colombier n = p - path; 3275e96a66cSDavid du Colombier if(n > 0){ 3285e96a66cSDavid du Colombier if(n > VtMaxStringSize){ 329f8e525acSDavid du Colombier vtSetError("%s: element too long", EBadPath); 3305e96a66cSDavid du Colombier goto Err; 3315e96a66cSDavid du Colombier } 3325e96a66cSDavid du Colombier memmove(elem, path, n); 3335e96a66cSDavid du Colombier elem[n] = 0; 3345e96a66cSDavid du Colombier ff = _fileWalk(f, elem, partial && *p=='\0'); 335f8e525acSDavid du Colombier if(ff == nil){ 336f8e525acSDavid du Colombier vtSetError("%.*s: %R", utfnlen(opath, p-opath), opath); 3375e96a66cSDavid du Colombier goto Err; 338f8e525acSDavid du Colombier } 3395e96a66cSDavid du Colombier fileDecRef(f); 3405e96a66cSDavid du Colombier f = ff; 3415e96a66cSDavid du Colombier } 3425e96a66cSDavid du Colombier if(*p == '/') 3435e96a66cSDavid du Colombier p++; 3445e96a66cSDavid du Colombier path = p; 3455e96a66cSDavid du Colombier } 3465e96a66cSDavid du Colombier return f; 3475e96a66cSDavid du Colombier Err: 3485e96a66cSDavid du Colombier fileDecRef(f); 3495e96a66cSDavid du Colombier return nil; 3505e96a66cSDavid du Colombier } 3515e96a66cSDavid du Colombier 3525e96a66cSDavid du Colombier File* 3535e96a66cSDavid du Colombier fileOpen(Fs *fs, char *path) 3545e96a66cSDavid du Colombier { 3555e96a66cSDavid du Colombier return _fileOpen(fs, path, 0); 3565e96a66cSDavid du Colombier } 3575e96a66cSDavid du Colombier 358*fe853e23SDavid du Colombier static void 359*fe853e23SDavid du Colombier fileSetTmp(File *f, int istmp) 360*fe853e23SDavid du Colombier { 361*fe853e23SDavid du Colombier int i; 362*fe853e23SDavid du Colombier Entry e; 363*fe853e23SDavid du Colombier Source *r; 364*fe853e23SDavid du Colombier 365*fe853e23SDavid du Colombier for(i=0; i<2; i++){ 366*fe853e23SDavid du Colombier if(i==0) 367*fe853e23SDavid du Colombier r = f->source; 368*fe853e23SDavid du Colombier else 369*fe853e23SDavid du Colombier r = f->msource; 370*fe853e23SDavid du Colombier if(r == nil) 371*fe853e23SDavid du Colombier continue; 372*fe853e23SDavid du Colombier if(!sourceGetEntry(f->source, &e)){ 373*fe853e23SDavid du Colombier fprint(2, "sourceGetEntry failed (cannot happen): %r\n"); 374*fe853e23SDavid du Colombier continue; 375*fe853e23SDavid du Colombier } 376*fe853e23SDavid du Colombier if(istmp) 377*fe853e23SDavid du Colombier e.flags |= VtEntryNoArchive; 378*fe853e23SDavid du Colombier else 379*fe853e23SDavid du Colombier e.flags &= ~VtEntryNoArchive; 380*fe853e23SDavid du Colombier if(!sourceSetEntry(f->source, &e)){ 381*fe853e23SDavid du Colombier fprint(2, "sourceSetEntry failed (cannot happen): %r\n"); 382*fe853e23SDavid du Colombier continue; 383*fe853e23SDavid du Colombier } 384*fe853e23SDavid du Colombier } 385*fe853e23SDavid du Colombier } 386*fe853e23SDavid du Colombier 3875e96a66cSDavid du Colombier File * 3885e96a66cSDavid du Colombier fileCreate(File *f, char *elem, ulong mode, char *uid) 3895e96a66cSDavid du Colombier { 3905e96a66cSDavid du Colombier File *ff; 3915e96a66cSDavid du Colombier DirEntry *dir; 3925e96a66cSDavid du Colombier Source *pr, *r, *mr; 3935e96a66cSDavid du Colombier int isdir; 3945e96a66cSDavid du Colombier 3955e96a66cSDavid du Colombier if(!fileLock(f)) 3965e96a66cSDavid du Colombier return nil; 3975e96a66cSDavid du Colombier 3985e96a66cSDavid du Colombier r = nil; 3995e96a66cSDavid du Colombier mr = nil; 4005e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 4015e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 4025e96a66cSDavid du Colombier ff = nil; 4035e96a66cSDavid du Colombier vtSetError(EExists); 4045e96a66cSDavid du Colombier goto Err1; 4055e96a66cSDavid du Colombier } 4065e96a66cSDavid du Colombier } 4075e96a66cSDavid du Colombier 4085e96a66cSDavid du Colombier ff = dirLookup(f, elem); 4095e96a66cSDavid du Colombier if(ff != nil){ 4105e96a66cSDavid du Colombier vtSetError(EExists); 4115e96a66cSDavid du Colombier goto Err1; 4125e96a66cSDavid du Colombier } 4135e96a66cSDavid du Colombier 4145e96a66cSDavid du Colombier pr = f->source; 4155e96a66cSDavid du Colombier if(pr->mode != OReadWrite){ 4165e96a66cSDavid du Colombier vtSetError(EReadOnly); 4175e96a66cSDavid du Colombier goto Err1; 4185e96a66cSDavid du Colombier } 4195e96a66cSDavid du Colombier 4205e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 4215e96a66cSDavid du Colombier goto Err1; 4225e96a66cSDavid du Colombier 4235e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 4245e96a66cSDavid du Colombier isdir = mode & ModeDir; 4255e96a66cSDavid du Colombier 4265e96a66cSDavid du Colombier r = sourceCreate(pr, pr->dsize, isdir, 0); 4275e96a66cSDavid du Colombier if(r == nil) 4285e96a66cSDavid du Colombier goto Err; 4295e96a66cSDavid du Colombier if(isdir){ 4305e96a66cSDavid du Colombier mr = sourceCreate(pr, pr->dsize, 0, r->offset); 4315e96a66cSDavid du Colombier if(mr == nil) 4325e96a66cSDavid du Colombier goto Err; 4335e96a66cSDavid du Colombier } 4345e96a66cSDavid du Colombier 4355e96a66cSDavid du Colombier dir = &ff->dir; 4365e96a66cSDavid du Colombier dir->elem = vtStrDup(elem); 4375e96a66cSDavid du Colombier dir->entry = r->offset; 4385e96a66cSDavid du Colombier dir->gen = r->gen; 4395e96a66cSDavid du Colombier if(isdir){ 4405e96a66cSDavid du Colombier dir->mentry = mr->offset; 4415e96a66cSDavid du Colombier dir->mgen = mr->gen; 4425e96a66cSDavid du Colombier } 4435e96a66cSDavid du Colombier dir->size = 0; 4445e96a66cSDavid du Colombier if(!fsNextQid(f->fs, &dir->qid)) 4455e96a66cSDavid du Colombier goto Err; 4465e96a66cSDavid du Colombier dir->uid = vtStrDup(uid); 4475e96a66cSDavid du Colombier dir->gid = vtStrDup(f->dir.gid); 4485e96a66cSDavid du Colombier dir->mid = vtStrDup(uid); 4495e96a66cSDavid du Colombier dir->mtime = time(0L); 4505e96a66cSDavid du Colombier dir->mcount = 0; 4515e96a66cSDavid du Colombier dir->ctime = dir->mtime; 4525e96a66cSDavid du Colombier dir->atime = dir->mtime; 4535e96a66cSDavid du Colombier dir->mode = mode; 4545e96a66cSDavid du Colombier 4555e96a66cSDavid du Colombier ff->boff = fileMetaAlloc(f, dir, 0); 4565e96a66cSDavid du Colombier if(ff->boff == NilBlock) 4575e96a66cSDavid du Colombier goto Err; 4585e96a66cSDavid du Colombier 4595e96a66cSDavid du Colombier sourceUnlock(f->source); 4605e96a66cSDavid du Colombier sourceUnlock(f->msource); 4615e96a66cSDavid du Colombier 4625e96a66cSDavid du Colombier ff->source = r; 4635e96a66cSDavid du Colombier ff->msource = mr; 4645e96a66cSDavid du Colombier 465*fe853e23SDavid du Colombier if(mode&ModeTemporary){ 466*fe853e23SDavid du Colombier if(!sourceLock2(r, mr, -1)) 467*fe853e23SDavid du Colombier goto Err1; 468*fe853e23SDavid du Colombier fileSetTmp(ff, 1); 469*fe853e23SDavid du Colombier sourceUnlock(r); 470*fe853e23SDavid du Colombier if(mr) 471*fe853e23SDavid du Colombier sourceUnlock(mr); 472*fe853e23SDavid du Colombier } 473*fe853e23SDavid du Colombier 474*fe853e23SDavid du Colombier /* committed */ 475*fe853e23SDavid du Colombier 4765e96a66cSDavid du Colombier /* link in and up parent ref count */ 4775e96a66cSDavid du Colombier ff->next = f->down; 4785e96a66cSDavid du Colombier f->down = ff; 4795e96a66cSDavid du Colombier ff->up = f; 4805e96a66cSDavid du Colombier fileIncRef(f); 4815e96a66cSDavid du Colombier 4825e96a66cSDavid du Colombier fileWAccess(f, uid); 4835e96a66cSDavid du Colombier 4845e96a66cSDavid du Colombier fileUnlock(f); 4855e96a66cSDavid du Colombier return ff; 4865e96a66cSDavid du Colombier 4875e96a66cSDavid du Colombier Err: 4885e96a66cSDavid du Colombier sourceUnlock(f->source); 4895e96a66cSDavid du Colombier sourceUnlock(f->msource); 4905e96a66cSDavid du Colombier Err1: 491dc5a79c1SDavid du Colombier if(r){ 492dc5a79c1SDavid du Colombier sourceLock(r, -1); 4935e96a66cSDavid du Colombier sourceRemove(r); 494dc5a79c1SDavid du Colombier } 495dc5a79c1SDavid du Colombier if(mr){ 496dc5a79c1SDavid du Colombier sourceLock(mr, -1); 4975e96a66cSDavid du Colombier sourceRemove(mr); 498dc5a79c1SDavid du Colombier } 4995e96a66cSDavid du Colombier if(ff) 5005e96a66cSDavid du Colombier fileDecRef(ff); 5015e96a66cSDavid du Colombier fileUnlock(f); 5025e96a66cSDavid du Colombier return 0; 5035e96a66cSDavid du Colombier } 5045e96a66cSDavid du Colombier 5055e96a66cSDavid du Colombier int 5065e96a66cSDavid du Colombier fileRead(File *f, void *buf, int cnt, vlong offset) 5075e96a66cSDavid du Colombier { 5085e96a66cSDavid du Colombier Source *s; 5095e96a66cSDavid du Colombier uvlong size; 5105e96a66cSDavid du Colombier u32int bn; 5115e96a66cSDavid du Colombier int off, dsize, n, nn; 5125e96a66cSDavid du Colombier Block *b; 5135e96a66cSDavid du Colombier uchar *p; 5145e96a66cSDavid du Colombier 5155e96a66cSDavid du Colombier if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset); 5165e96a66cSDavid du Colombier 5175e96a66cSDavid du Colombier if(!fileRLock(f)) 5185e96a66cSDavid du Colombier return -1; 5195e96a66cSDavid du Colombier 5205e96a66cSDavid du Colombier if(offset < 0){ 5215e96a66cSDavid du Colombier vtSetError(EBadOffset); 5225e96a66cSDavid du Colombier goto Err1; 5235e96a66cSDavid du Colombier } 5245e96a66cSDavid du Colombier 5255e96a66cSDavid du Colombier fileRAccess(f); 5265e96a66cSDavid du Colombier 5275e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)) 5285e96a66cSDavid du Colombier goto Err1; 5295e96a66cSDavid du Colombier 5305e96a66cSDavid du Colombier s = f->source; 5315e96a66cSDavid du Colombier dsize = s->dsize; 5325e96a66cSDavid du Colombier size = sourceGetSize(s); 5335e96a66cSDavid du Colombier 5345e96a66cSDavid du Colombier if(offset >= size) 5355e96a66cSDavid du Colombier offset = size; 5365e96a66cSDavid du Colombier 5375e96a66cSDavid du Colombier if(cnt > size-offset) 5385e96a66cSDavid du Colombier cnt = size-offset; 5395e96a66cSDavid du Colombier bn = offset/dsize; 5405e96a66cSDavid du Colombier off = offset%dsize; 5415e96a66cSDavid du Colombier p = buf; 5425e96a66cSDavid du Colombier while(cnt > 0){ 5435e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 5445e96a66cSDavid du Colombier if(b == nil) 5455e96a66cSDavid du Colombier goto Err; 5465e96a66cSDavid du Colombier n = cnt; 5475e96a66cSDavid du Colombier if(n > dsize-off) 5485e96a66cSDavid du Colombier n = dsize-off; 5495e96a66cSDavid du Colombier nn = dsize-off; 5505e96a66cSDavid du Colombier if(nn > n) 5515e96a66cSDavid du Colombier nn = n; 5525e96a66cSDavid du Colombier memmove(p, b->data+off, nn); 5535e96a66cSDavid du Colombier memset(p+nn, 0, nn-n); 5545e96a66cSDavid du Colombier off = 0; 5555e96a66cSDavid du Colombier bn++; 5565e96a66cSDavid du Colombier cnt -= n; 5575e96a66cSDavid du Colombier p += n; 5585e96a66cSDavid du Colombier blockPut(b); 5595e96a66cSDavid du Colombier } 5605e96a66cSDavid du Colombier sourceUnlock(s); 5615e96a66cSDavid du Colombier fileRUnlock(f); 5625e96a66cSDavid du Colombier return p-(uchar*)buf; 5635e96a66cSDavid du Colombier 5645e96a66cSDavid du Colombier Err: 5655e96a66cSDavid du Colombier sourceUnlock(s); 5665e96a66cSDavid du Colombier Err1: 5675e96a66cSDavid du Colombier fileRUnlock(f); 5685e96a66cSDavid du Colombier return -1; 5695e96a66cSDavid du Colombier } 5705e96a66cSDavid du Colombier 571*fe853e23SDavid du Colombier /* 572*fe853e23SDavid du Colombier * Changes the file block bn to be the given block score. 573*fe853e23SDavid du Colombier * Very sneaky. Only used by flfmt. 574*fe853e23SDavid du Colombier */ 575*fe853e23SDavid du Colombier int 576*fe853e23SDavid du Colombier fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag) 577*fe853e23SDavid du Colombier { 578*fe853e23SDavid du Colombier Block *b; 579*fe853e23SDavid du Colombier Entry e; 580*fe853e23SDavid du Colombier Source *s; 581*fe853e23SDavid du Colombier 582*fe853e23SDavid du Colombier if(!fileLock(f)) 583*fe853e23SDavid du Colombier return 0; 584*fe853e23SDavid du Colombier 585*fe853e23SDavid du Colombier s = nil; 586*fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){ 587*fe853e23SDavid du Colombier vtSetError(ENotFile); 588*fe853e23SDavid du Colombier goto Err; 589*fe853e23SDavid du Colombier } 590*fe853e23SDavid du Colombier 591*fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){ 592*fe853e23SDavid du Colombier vtSetError(EReadOnly); 593*fe853e23SDavid du Colombier goto Err; 594*fe853e23SDavid du Colombier } 595*fe853e23SDavid du Colombier 596*fe853e23SDavid du Colombier if(!sourceLock(f->source, -1)) 597*fe853e23SDavid du Colombier goto Err; 598*fe853e23SDavid du Colombier 599*fe853e23SDavid du Colombier s = f->source; 600*fe853e23SDavid du Colombier b = _sourceBlock(s, bn, OReadWrite, 1, tag); 601*fe853e23SDavid du Colombier if(b == nil) 602*fe853e23SDavid du Colombier goto Err; 603*fe853e23SDavid du Colombier 604*fe853e23SDavid du Colombier if(!sourceGetEntry(s, &e)) 605*fe853e23SDavid du Colombier goto Err; 606*fe853e23SDavid du Colombier if(b->l.type == BtDir){ 607*fe853e23SDavid du Colombier memmove(e.score, score, VtScoreSize); 608*fe853e23SDavid du Colombier assert(e.tag == tag || e.tag == 0); 609*fe853e23SDavid du Colombier e.tag = tag; 610*fe853e23SDavid du Colombier e.flags |= VtEntryLocal; 611*fe853e23SDavid du Colombier entryPack(&e, b->data, f->source->offset % f->source->epb); 612*fe853e23SDavid du Colombier }else 613*fe853e23SDavid du Colombier memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize); 614*fe853e23SDavid du Colombier blockDirty(b); 615*fe853e23SDavid du Colombier blockPut(b); 616*fe853e23SDavid du Colombier sourceUnlock(s); 617*fe853e23SDavid du Colombier fileUnlock(f); 618*fe853e23SDavid du Colombier return 1; 619*fe853e23SDavid du Colombier 620*fe853e23SDavid du Colombier Err: 621*fe853e23SDavid du Colombier if(s) 622*fe853e23SDavid du Colombier sourceUnlock(s); 623*fe853e23SDavid du Colombier fileUnlock(f); 624*fe853e23SDavid du Colombier return 0; 625*fe853e23SDavid du Colombier } 626*fe853e23SDavid du Colombier 627*fe853e23SDavid du Colombier int 628*fe853e23SDavid du Colombier fileSetSize(File *f, uvlong size) 629*fe853e23SDavid du Colombier { 630*fe853e23SDavid du Colombier int r; 631*fe853e23SDavid du Colombier 632*fe853e23SDavid du Colombier if(!fileLock(f)) 633*fe853e23SDavid du Colombier return 0; 634*fe853e23SDavid du Colombier r = 0; 635*fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){ 636*fe853e23SDavid du Colombier vtSetError(ENotFile); 637*fe853e23SDavid du Colombier goto Err; 638*fe853e23SDavid du Colombier } 639*fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){ 640*fe853e23SDavid du Colombier vtSetError(EReadOnly); 641*fe853e23SDavid du Colombier goto Err; 642*fe853e23SDavid du Colombier } 643*fe853e23SDavid du Colombier if(!sourceLock(f->source, -1)) 644*fe853e23SDavid du Colombier goto Err; 645*fe853e23SDavid du Colombier r = sourceSetSize(f->source, size); 646*fe853e23SDavid du Colombier sourceUnlock(f->source); 647*fe853e23SDavid du Colombier Err: 648*fe853e23SDavid du Colombier fileUnlock(f); 649*fe853e23SDavid du Colombier return r; 650*fe853e23SDavid du Colombier } 651*fe853e23SDavid du Colombier 6525e96a66cSDavid du Colombier int 6535e96a66cSDavid du Colombier fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid) 6545e96a66cSDavid du Colombier { 6555e96a66cSDavid du Colombier Source *s; 6565e96a66cSDavid du Colombier ulong bn; 6575e96a66cSDavid du Colombier int off, dsize, n; 6585e96a66cSDavid du Colombier Block *b; 6595e96a66cSDavid du Colombier uchar *p; 6605e96a66cSDavid du Colombier vlong eof; 6615e96a66cSDavid du Colombier 6625e96a66cSDavid du Colombier if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); 6635e96a66cSDavid du Colombier 6645e96a66cSDavid du Colombier if(!fileLock(f)) 6655e96a66cSDavid du Colombier return -1; 6665e96a66cSDavid du Colombier 6675e96a66cSDavid du Colombier s = nil; 6685e96a66cSDavid du Colombier if(f->dir.mode & ModeDir){ 6695e96a66cSDavid du Colombier vtSetError(ENotFile); 6705e96a66cSDavid du Colombier goto Err; 6715e96a66cSDavid du Colombier } 6725e96a66cSDavid du Colombier 6735e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 6745e96a66cSDavid du Colombier vtSetError(EReadOnly); 6755e96a66cSDavid du Colombier goto Err; 6765e96a66cSDavid du Colombier } 6775e96a66cSDavid du Colombier if(offset < 0){ 6785e96a66cSDavid du Colombier vtSetError(EBadOffset); 6795e96a66cSDavid du Colombier goto Err; 6805e96a66cSDavid du Colombier } 6815e96a66cSDavid du Colombier 6825e96a66cSDavid du Colombier fileWAccess(f, uid); 6835e96a66cSDavid du Colombier 6845e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 6855e96a66cSDavid du Colombier goto Err; 6865e96a66cSDavid du Colombier s = f->source; 6875e96a66cSDavid du Colombier dsize = s->dsize; 6885e96a66cSDavid du Colombier 6895e96a66cSDavid du Colombier eof = sourceGetSize(s); 6905e96a66cSDavid du Colombier if(f->dir.mode & ModeAppend) 6915e96a66cSDavid du Colombier offset = eof; 6925e96a66cSDavid du Colombier bn = offset/dsize; 6935e96a66cSDavid du Colombier off = offset%dsize; 6945e96a66cSDavid du Colombier p = buf; 6955e96a66cSDavid du Colombier while(cnt > 0){ 6965e96a66cSDavid du Colombier n = cnt; 6975e96a66cSDavid du Colombier if(n > dsize-off) 6985e96a66cSDavid du Colombier n = dsize-off; 6995e96a66cSDavid du Colombier b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite); 7005e96a66cSDavid du Colombier if(b == nil){ 7015e96a66cSDavid du Colombier if(offset > eof) 7025e96a66cSDavid du Colombier sourceSetSize(s, offset); 7035e96a66cSDavid du Colombier goto Err; 7045e96a66cSDavid du Colombier } 7055e96a66cSDavid du Colombier memmove(b->data+off, p, n); 7065e96a66cSDavid du Colombier off = 0; 7075e96a66cSDavid du Colombier cnt -= n; 7085e96a66cSDavid du Colombier p += n; 7095e96a66cSDavid du Colombier offset += n; 7105e96a66cSDavid du Colombier bn++; 7115e96a66cSDavid du Colombier blockDirty(b); 7125e96a66cSDavid du Colombier blockPut(b); 7135e96a66cSDavid du Colombier } 7145e96a66cSDavid du Colombier if(offset > eof && !sourceSetSize(s, offset)) 7155e96a66cSDavid du Colombier goto Err; 7165e96a66cSDavid du Colombier sourceUnlock(s); 7175e96a66cSDavid du Colombier fileUnlock(f); 7185e96a66cSDavid du Colombier return p-(uchar*)buf; 7195e96a66cSDavid du Colombier Err: 7205e96a66cSDavid du Colombier if(s) 7215e96a66cSDavid du Colombier sourceUnlock(s); 7225e96a66cSDavid du Colombier fileUnlock(f); 7235e96a66cSDavid du Colombier return -1; 7245e96a66cSDavid du Colombier } 7255e96a66cSDavid du Colombier 7265e96a66cSDavid du Colombier int 7275e96a66cSDavid du Colombier fileGetDir(File *f, DirEntry *dir) 7285e96a66cSDavid du Colombier { 7295e96a66cSDavid du Colombier if(!fileRLock(f)) 7305e96a66cSDavid du Colombier return 0; 7315e96a66cSDavid du Colombier 7325e96a66cSDavid du Colombier fileMetaLock(f); 7335e96a66cSDavid du Colombier deCopy(dir, &f->dir); 7345e96a66cSDavid du Colombier fileMetaUnlock(f); 7355e96a66cSDavid du Colombier 7365e96a66cSDavid du Colombier if(!fileIsDir(f)){ 7375e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 7385e96a66cSDavid du Colombier fileRUnlock(f); 7395e96a66cSDavid du Colombier return 0; 7405e96a66cSDavid du Colombier } 7415e96a66cSDavid du Colombier dir->size = sourceGetSize(f->source); 7425e96a66cSDavid du Colombier sourceUnlock(f->source); 7435e96a66cSDavid du Colombier } 7445e96a66cSDavid du Colombier fileRUnlock(f); 7455e96a66cSDavid du Colombier 7465e96a66cSDavid du Colombier return 1; 7475e96a66cSDavid du Colombier } 7485e96a66cSDavid du Colombier 7495e96a66cSDavid du Colombier int 7505e96a66cSDavid du Colombier fileTruncate(File *f, char *uid) 7515e96a66cSDavid du Colombier { 7525e96a66cSDavid du Colombier if(fileIsDir(f)){ 7535e96a66cSDavid du Colombier vtSetError(ENotFile); 7545e96a66cSDavid du Colombier return 0; 7555e96a66cSDavid du Colombier } 7565e96a66cSDavid du Colombier 7575e96a66cSDavid du Colombier if(!fileLock(f)) 7585e96a66cSDavid du Colombier return 0; 7595e96a66cSDavid du Colombier 7605e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 7615e96a66cSDavid du Colombier vtSetError(EReadOnly); 7625e96a66cSDavid du Colombier fileUnlock(f); 7635e96a66cSDavid du Colombier return 0; 7645e96a66cSDavid du Colombier } 7655e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)){ 7665e96a66cSDavid du Colombier fileUnlock(f); 7675e96a66cSDavid du Colombier return 0; 7685e96a66cSDavid du Colombier } 7695e96a66cSDavid du Colombier if(!sourceTruncate(f->source)){ 7705e96a66cSDavid du Colombier sourceUnlock(f->source); 7715e96a66cSDavid du Colombier fileUnlock(f); 7725e96a66cSDavid du Colombier return 0; 7735e96a66cSDavid du Colombier } 7745e96a66cSDavid du Colombier sourceUnlock(f->source); 7755e96a66cSDavid du Colombier fileUnlock(f); 7765e96a66cSDavid du Colombier 777a960ed1cSDavid du Colombier fileWAccess(f, uid); 7785e96a66cSDavid du Colombier 7795e96a66cSDavid du Colombier return 1; 7805e96a66cSDavid du Colombier } 7815e96a66cSDavid du Colombier 7825e96a66cSDavid du Colombier int 7835e96a66cSDavid du Colombier fileSetDir(File *f, DirEntry *dir, char *uid) 7845e96a66cSDavid du Colombier { 7855e96a66cSDavid du Colombier File *ff; 7865e96a66cSDavid du Colombier char *oelem; 7875e96a66cSDavid du Colombier u32int mask; 7885e96a66cSDavid du Colombier u64int size; 7895e96a66cSDavid du Colombier 7905e96a66cSDavid du Colombier /* can not set permissions for the root */ 7915e96a66cSDavid du Colombier if(fileIsRoot(f)){ 7925e96a66cSDavid du Colombier vtSetError(ERoot); 7935e96a66cSDavid du Colombier return 0; 7945e96a66cSDavid du Colombier } 7955e96a66cSDavid du Colombier 7965e96a66cSDavid du Colombier if(!fileLock(f)) 7975e96a66cSDavid du Colombier return 0; 7985e96a66cSDavid du Colombier 7995e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 8005e96a66cSDavid du Colombier vtSetError(EReadOnly); 8015e96a66cSDavid du Colombier fileUnlock(f); 8025e96a66cSDavid du Colombier return 0; 8035e96a66cSDavid du Colombier } 8045e96a66cSDavid du Colombier 8055e96a66cSDavid du Colombier fileMetaLock(f); 8065e96a66cSDavid du Colombier 8075e96a66cSDavid du Colombier /* check new name does not already exist */ 8085e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 8095e96a66cSDavid du Colombier for(ff = f->up->down; ff; ff=ff->next){ 8105e96a66cSDavid du Colombier if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ 8115e96a66cSDavid du Colombier vtSetError(EExists); 8125e96a66cSDavid du Colombier goto Err; 8135e96a66cSDavid du Colombier } 8145e96a66cSDavid du Colombier } 8155e96a66cSDavid du Colombier 8165e96a66cSDavid du Colombier ff = dirLookup(f->up, dir->elem); 8175e96a66cSDavid du Colombier if(ff != nil){ 8185e96a66cSDavid du Colombier fileDecRef(ff); 8195e96a66cSDavid du Colombier vtSetError(EExists); 8205e96a66cSDavid du Colombier goto Err; 8215e96a66cSDavid du Colombier } 8225e96a66cSDavid du Colombier } 8235e96a66cSDavid du Colombier 824*fe853e23SDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 8255e96a66cSDavid du Colombier goto Err; 826*fe853e23SDavid du Colombier if(!fileIsDir(f)){ 8275e96a66cSDavid du Colombier size = sourceGetSize(f->source); 8285e96a66cSDavid du Colombier if(size != dir->size){ 8295e96a66cSDavid du Colombier if(!sourceSetSize(f->source, dir->size)){ 8305e96a66cSDavid du Colombier sourceUnlock(f->source); 831*fe853e23SDavid du Colombier if(f->msource) 832*fe853e23SDavid du Colombier sourceUnlock(f->msource); 8335e96a66cSDavid du Colombier goto Err; 8345e96a66cSDavid du Colombier } 8355e96a66cSDavid du Colombier /* commited to changing it now */ 8365e96a66cSDavid du Colombier } 8375e96a66cSDavid du Colombier } 8385e96a66cSDavid du Colombier /* commited to changing it now */ 839*fe853e23SDavid du Colombier if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary)) 840*fe853e23SDavid du Colombier fileSetTmp(f, dir->mode&ModeTemporary); 841*fe853e23SDavid du Colombier sourceUnlock(f->source); 842*fe853e23SDavid du Colombier if(f->msource) 843*fe853e23SDavid du Colombier sourceUnlock(f->msource); 844*fe853e23SDavid du Colombier 8455e96a66cSDavid du Colombier oelem = nil; 8465e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 8475e96a66cSDavid du Colombier oelem = f->dir.elem; 8485e96a66cSDavid du Colombier f->dir.elem = vtStrDup(dir->elem); 8495e96a66cSDavid du Colombier } 8505e96a66cSDavid du Colombier 8515e96a66cSDavid du Colombier if(strcmp(f->dir.uid, dir->uid) != 0){ 8525e96a66cSDavid du Colombier vtMemFree(f->dir.uid); 8535e96a66cSDavid du Colombier f->dir.uid = vtStrDup(dir->uid); 8545e96a66cSDavid du Colombier } 8555e96a66cSDavid du Colombier 8565e96a66cSDavid du Colombier if(strcmp(f->dir.gid, dir->gid) != 0){ 8575e96a66cSDavid du Colombier vtMemFree(f->dir.gid); 8585e96a66cSDavid du Colombier f->dir.gid = vtStrDup(dir->gid); 8595e96a66cSDavid du Colombier } 8605e96a66cSDavid du Colombier 8615e96a66cSDavid du Colombier f->dir.mtime = dir->mtime; 8625e96a66cSDavid du Colombier f->dir.atime = dir->atime; 8635e96a66cSDavid du Colombier 8645e96a66cSDavid du Colombier //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); 8655e96a66cSDavid du Colombier mask = ~(ModeDir|ModeSnapshot); 8665e96a66cSDavid du Colombier f->dir.mode &= ~mask; 8675e96a66cSDavid du Colombier f->dir.mode |= mask & dir->mode; 8685e96a66cSDavid du Colombier f->dirty = 1; 8695e96a66cSDavid du Colombier //fprint(2, "->%x\n", f->dir.mode); 8705e96a66cSDavid du Colombier 8715e96a66cSDavid du Colombier fileMetaFlush2(f, oelem); 8725e96a66cSDavid du Colombier vtMemFree(oelem); 8735e96a66cSDavid du Colombier 8745e96a66cSDavid du Colombier fileMetaUnlock(f); 8755e96a66cSDavid du Colombier fileUnlock(f); 8765e96a66cSDavid du Colombier 8775e96a66cSDavid du Colombier fileWAccess(f->up, uid); 8785e96a66cSDavid du Colombier 8795e96a66cSDavid du Colombier return 1; 8805e96a66cSDavid du Colombier Err: 8815e96a66cSDavid du Colombier fileMetaUnlock(f); 8825e96a66cSDavid du Colombier fileUnlock(f); 8835e96a66cSDavid du Colombier return 0; 8845e96a66cSDavid du Colombier } 8855e96a66cSDavid du Colombier 8865e96a66cSDavid du Colombier int 8875e96a66cSDavid du Colombier fileSetQidSpace(File *f, u64int offset, u64int max) 8885e96a66cSDavid du Colombier { 8895e96a66cSDavid du Colombier int ret; 8905e96a66cSDavid du Colombier 8915e96a66cSDavid du Colombier if(!fileLock(f)) 8925e96a66cSDavid du Colombier return 0; 8935e96a66cSDavid du Colombier fileMetaLock(f); 8945e96a66cSDavid du Colombier f->dir.qidSpace = 1; 8955e96a66cSDavid du Colombier f->dir.qidOffset = offset; 8965e96a66cSDavid du Colombier f->dir.qidMax = max; 8975e96a66cSDavid du Colombier ret = fileMetaFlush2(f, nil); 8985e96a66cSDavid du Colombier fileMetaUnlock(f); 8995e96a66cSDavid du Colombier fileUnlock(f); 9005e96a66cSDavid du Colombier return ret; 9015e96a66cSDavid du Colombier } 9025e96a66cSDavid du Colombier 9035e96a66cSDavid du Colombier 9045e96a66cSDavid du Colombier uvlong 9055e96a66cSDavid du Colombier fileGetId(File *f) 9065e96a66cSDavid du Colombier { 9075e96a66cSDavid du Colombier /* immutable */ 9085e96a66cSDavid du Colombier return f->dir.qid; 9095e96a66cSDavid du Colombier } 9105e96a66cSDavid du Colombier 9115e96a66cSDavid du Colombier ulong 9125e96a66cSDavid du Colombier fileGetMcount(File *f) 9135e96a66cSDavid du Colombier { 9145e96a66cSDavid du Colombier ulong mcount; 9155e96a66cSDavid du Colombier 9165e96a66cSDavid du Colombier fileMetaLock(f); 9175e96a66cSDavid du Colombier mcount = f->dir.mcount; 9185e96a66cSDavid du Colombier fileMetaUnlock(f); 9195e96a66cSDavid du Colombier return mcount; 9205e96a66cSDavid du Colombier } 9215e96a66cSDavid du Colombier 9225e96a66cSDavid du Colombier ulong 9235e96a66cSDavid du Colombier fileGetMode(File *f) 9245e96a66cSDavid du Colombier { 9255e96a66cSDavid du Colombier ulong mode; 9265e96a66cSDavid du Colombier 9275e96a66cSDavid du Colombier fileMetaLock(f); 9285e96a66cSDavid du Colombier mode = f->dir.mode; 9295e96a66cSDavid du Colombier fileMetaUnlock(f); 9305e96a66cSDavid du Colombier return mode; 9315e96a66cSDavid du Colombier } 9325e96a66cSDavid du Colombier 9335e96a66cSDavid du Colombier int 9345e96a66cSDavid du Colombier fileIsDir(File *f) 9355e96a66cSDavid du Colombier { 9365e96a66cSDavid du Colombier /* immutable */ 9375e96a66cSDavid du Colombier return (f->dir.mode & ModeDir) != 0; 9385e96a66cSDavid du Colombier } 9395e96a66cSDavid du Colombier 9405e96a66cSDavid du Colombier int 9415e96a66cSDavid du Colombier fileIsRoot(File *f) 9425e96a66cSDavid du Colombier { 9435e96a66cSDavid du Colombier return f == f->fs->file; 9445e96a66cSDavid du Colombier } 9455e96a66cSDavid du Colombier 9465e96a66cSDavid du Colombier int 9475e96a66cSDavid du Colombier fileIsRoFs(File *f) 9485e96a66cSDavid du Colombier { 9495e96a66cSDavid du Colombier return f->fs->mode == OReadOnly; 9505e96a66cSDavid du Colombier } 9515e96a66cSDavid du Colombier 9525e96a66cSDavid du Colombier int 9535e96a66cSDavid du Colombier fileGetSize(File *f, uvlong *size) 9545e96a66cSDavid du Colombier { 9555e96a66cSDavid du Colombier if(!fileRLock(f)) 9565e96a66cSDavid du Colombier return 0; 9575e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 9585e96a66cSDavid du Colombier fileRUnlock(f); 9595e96a66cSDavid du Colombier return 0; 9605e96a66cSDavid du Colombier } 9615e96a66cSDavid du Colombier *size = sourceGetSize(f->source); 9625e96a66cSDavid du Colombier sourceUnlock(f->source); 9635e96a66cSDavid du Colombier fileRUnlock(f); 9645e96a66cSDavid du Colombier 9655e96a66cSDavid du Colombier return 1; 9665e96a66cSDavid du Colombier } 9675e96a66cSDavid du Colombier 9685e96a66cSDavid du Colombier void 9695e96a66cSDavid du Colombier fileMetaFlush(File *f, int rec) 9705e96a66cSDavid du Colombier { 9715e96a66cSDavid du Colombier File **kids, *p; 9725e96a66cSDavid du Colombier int nkids; 9735e96a66cSDavid du Colombier int i; 9745e96a66cSDavid du Colombier 9755e96a66cSDavid du Colombier fileMetaLock(f); 9765e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 9775e96a66cSDavid du Colombier fileMetaUnlock(f); 9785e96a66cSDavid du Colombier 9795e96a66cSDavid du Colombier if(!rec || !fileIsDir(f)) 9805e96a66cSDavid du Colombier return; 9815e96a66cSDavid du Colombier 9825e96a66cSDavid du Colombier if(!fileLock(f)) 9835e96a66cSDavid du Colombier return; 9845e96a66cSDavid du Colombier nkids = 0; 9855e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 9865e96a66cSDavid du Colombier nkids++; 9875e96a66cSDavid du Colombier kids = vtMemAlloc(nkids*sizeof(File*)); 9885e96a66cSDavid du Colombier i = 0; 9895e96a66cSDavid du Colombier for(p=f->down; p; p=p->next){ 9905e96a66cSDavid du Colombier kids[i++] = p; 9915e96a66cSDavid du Colombier p->ref++; 9925e96a66cSDavid du Colombier } 9935e96a66cSDavid du Colombier fileUnlock(f); 9945e96a66cSDavid du Colombier 9955e96a66cSDavid du Colombier for(i=0; i<nkids; i++){ 9965e96a66cSDavid du Colombier fileMetaFlush(kids[i], 1); 9975e96a66cSDavid du Colombier fileDecRef(kids[i]); 9985e96a66cSDavid du Colombier } 9995e96a66cSDavid du Colombier vtMemFree(kids); 10005e96a66cSDavid du Colombier } 10015e96a66cSDavid du Colombier 10025e96a66cSDavid du Colombier /* assumes metaLock is held */ 10035e96a66cSDavid du Colombier static int 10045e96a66cSDavid du Colombier fileMetaFlush2(File *f, char *oelem) 10055e96a66cSDavid du Colombier { 10065e96a66cSDavid du Colombier File *fp; 10075e96a66cSDavid du Colombier Block *b, *bb; 10085e96a66cSDavid du Colombier MetaBlock mb; 10095e96a66cSDavid du Colombier MetaEntry me, me2; 10105e96a66cSDavid du Colombier int i, n; 10115e96a66cSDavid du Colombier u32int boff; 10125e96a66cSDavid du Colombier 10135e96a66cSDavid du Colombier if(!f->dirty) 10145e96a66cSDavid du Colombier return 1; 10155e96a66cSDavid du Colombier 10165e96a66cSDavid du Colombier if(oelem == nil) 10175e96a66cSDavid du Colombier oelem = f->dir.elem; 10185e96a66cSDavid du Colombier 10195e96a66cSDavid du Colombier //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem); 10205e96a66cSDavid du Colombier 10215e96a66cSDavid du Colombier fp = f->up; 10225e96a66cSDavid du Colombier 10235e96a66cSDavid du Colombier if(!sourceLock(fp->msource, -1)) 10245e96a66cSDavid du Colombier return 0; 10256042bf6dSDavid du Colombier /* can happen if source is clri'ed out from under us */ 10266042bf6dSDavid du Colombier if(f->boff == NilBlock) 10276042bf6dSDavid du Colombier goto Err1; 10285e96a66cSDavid du Colombier b = sourceBlock(fp->msource, f->boff, OReadWrite); 10295e96a66cSDavid du Colombier if(b == nil) 10305e96a66cSDavid du Colombier goto Err1; 10315e96a66cSDavid du Colombier 10325e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, fp->msource->dsize)) 10335e96a66cSDavid du Colombier goto Err; 10345e96a66cSDavid du Colombier if(!mbSearch(&mb, oelem, &i, &me)) 10355e96a66cSDavid du Colombier goto Err; 10365e96a66cSDavid du Colombier 10375e96a66cSDavid du Colombier n = deSize(&f->dir); 10385e96a66cSDavid du Colombier if(0)fprint(2, "old size %d new size %d\n", me.size, n); 10395e96a66cSDavid du Colombier 10405e96a66cSDavid du Colombier if(mbResize(&mb, &me, n)){ 10415e96a66cSDavid du Colombier /* fits in the block */ 10425e96a66cSDavid du Colombier mbDelete(&mb, i); 10435e96a66cSDavid du Colombier if(strcmp(f->dir.elem, oelem) != 0) 10445e96a66cSDavid du Colombier mbSearch(&mb, f->dir.elem, &i, &me2); 10455e96a66cSDavid du Colombier dePack(&f->dir, &me); 10465e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 10475e96a66cSDavid du Colombier mbPack(&mb); 10485e96a66cSDavid du Colombier blockDirty(b); 10495e96a66cSDavid du Colombier blockPut(b); 10505e96a66cSDavid du Colombier sourceUnlock(fp->msource); 10515e96a66cSDavid du Colombier f->dirty = 0; 10525e96a66cSDavid du Colombier 10535e96a66cSDavid du Colombier return 1; 10545e96a66cSDavid du Colombier } 10555e96a66cSDavid du Colombier 10565e96a66cSDavid du Colombier /* 10575e96a66cSDavid du Colombier * moving entry to another block 10585e96a66cSDavid du Colombier * it is feasible for the fs to crash leaving two copies 10595e96a66cSDavid du Colombier * of the directory entry. This is just too much work to 10605e96a66cSDavid du Colombier * fix. Given that entries are only allocated in a block that 10615e96a66cSDavid du Colombier * is less than PercentageFull, most modifications of meta data 10625e96a66cSDavid du Colombier * will fit within the block. i.e. this code should almost 10635e96a66cSDavid du Colombier * never be executed. 10645e96a66cSDavid du Colombier */ 10655e96a66cSDavid du Colombier boff = fileMetaAlloc(fp, &f->dir, f->boff+1); 10665e96a66cSDavid du Colombier if(boff == NilBlock){ 10675e96a66cSDavid du Colombier /* mbResize might have modified block */ 10685e96a66cSDavid du Colombier mbPack(&mb); 10695e96a66cSDavid du Colombier blockDirty(b); 10705e96a66cSDavid du Colombier goto Err; 10715e96a66cSDavid du Colombier } 10725e96a66cSDavid du Colombier fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff); 10735e96a66cSDavid du Colombier f->boff = boff; 10745e96a66cSDavid du Colombier 10755e96a66cSDavid du Colombier /* make sure deletion goes to disk after new entry */ 10765e96a66cSDavid du Colombier bb = sourceBlock(fp->msource, f->boff, OReadWrite); 10775e96a66cSDavid du Colombier mbDelete(&mb, i); 10785e96a66cSDavid du Colombier mbPack(&mb); 107961201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 10805e96a66cSDavid du Colombier blockPut(bb); 10815e96a66cSDavid du Colombier blockDirty(b); 10825e96a66cSDavid du Colombier blockPut(b); 10835e96a66cSDavid du Colombier sourceUnlock(fp->msource); 10845e96a66cSDavid du Colombier 10855e96a66cSDavid du Colombier f->dirty = 0; 10865e96a66cSDavid du Colombier 10875e96a66cSDavid du Colombier return 1; 10885e96a66cSDavid du Colombier 10895e96a66cSDavid du Colombier Err: 10905e96a66cSDavid du Colombier blockPut(b); 10915e96a66cSDavid du Colombier Err1: 10925e96a66cSDavid du Colombier sourceUnlock(fp->msource); 10935e96a66cSDavid du Colombier return 0; 10945e96a66cSDavid du Colombier } 10955e96a66cSDavid du Colombier 10965e96a66cSDavid du Colombier static int 10975e96a66cSDavid du Colombier fileMetaRemove(File *f, char *uid) 10985e96a66cSDavid du Colombier { 10995e96a66cSDavid du Colombier Block *b; 11005e96a66cSDavid du Colombier MetaBlock mb; 11015e96a66cSDavid du Colombier MetaEntry me; 11025e96a66cSDavid du Colombier int i; 11035e96a66cSDavid du Colombier File *up; 11045e96a66cSDavid du Colombier 11055e96a66cSDavid du Colombier up = f->up; 11065e96a66cSDavid du Colombier 11075e96a66cSDavid du Colombier fileWAccess(up, uid); 11085e96a66cSDavid du Colombier 11095e96a66cSDavid du Colombier fileMetaLock(f); 11105e96a66cSDavid du Colombier 11115e96a66cSDavid du Colombier sourceLock(up->msource, OReadWrite); 11125e96a66cSDavid du Colombier b = sourceBlock(up->msource, f->boff, OReadWrite); 11135e96a66cSDavid du Colombier if(b == nil) 11145e96a66cSDavid du Colombier goto Err; 11155e96a66cSDavid du Colombier 11165e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, up->msource->dsize)) 11175e96a66cSDavid du Colombier { 11185e96a66cSDavid du Colombier fprint(2, "U\n"); 11195e96a66cSDavid du Colombier goto Err; 11205e96a66cSDavid du Colombier } 11215e96a66cSDavid du Colombier if(!mbSearch(&mb, f->dir.elem, &i, &me)) 11225e96a66cSDavid du Colombier { 11235e96a66cSDavid du Colombier fprint(2, "S\n"); 11245e96a66cSDavid du Colombier goto Err; 11255e96a66cSDavid du Colombier } 11265e96a66cSDavid du Colombier mbDelete(&mb, i); 11275e96a66cSDavid du Colombier mbPack(&mb); 11285e96a66cSDavid du Colombier sourceUnlock(up->msource); 11295e96a66cSDavid du Colombier 11305e96a66cSDavid du Colombier blockDirty(b); 11315e96a66cSDavid du Colombier blockPut(b); 11325e96a66cSDavid du Colombier 11335e96a66cSDavid du Colombier f->removed = 1; 11345e96a66cSDavid du Colombier f->boff = NilBlock; 11355e96a66cSDavid du Colombier f->dirty = 0; 11365e96a66cSDavid du Colombier 11375e96a66cSDavid du Colombier fileMetaUnlock(f); 11385e96a66cSDavid du Colombier return 1; 11395e96a66cSDavid du Colombier 11405e96a66cSDavid du Colombier Err: 11415e96a66cSDavid du Colombier sourceUnlock(up->msource); 11425e96a66cSDavid du Colombier blockPut(b); 11435e96a66cSDavid du Colombier fileMetaUnlock(f); 11445e96a66cSDavid du Colombier return 0; 11455e96a66cSDavid du Colombier } 11465e96a66cSDavid du Colombier 11475e96a66cSDavid du Colombier /* assume file is locked, assume f->msource is locked */ 11485e96a66cSDavid du Colombier static int 11495e96a66cSDavid du Colombier fileCheckEmpty(File *f) 11505e96a66cSDavid du Colombier { 11515e96a66cSDavid du Colombier u32int i, n; 11525e96a66cSDavid du Colombier Block *b; 11535e96a66cSDavid du Colombier MetaBlock mb; 11545e96a66cSDavid du Colombier Source *r; 11555e96a66cSDavid du Colombier 11565e96a66cSDavid du Colombier r = f->msource; 11575e96a66cSDavid du Colombier n = (sourceGetSize(r)+r->dsize-1)/r->dsize; 11585e96a66cSDavid du Colombier for(i=0; i<n; i++){ 11595e96a66cSDavid du Colombier b = sourceBlock(r, i, OReadOnly); 11605e96a66cSDavid du Colombier if(b == nil) 11615e96a66cSDavid du Colombier goto Err; 11625e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, r->dsize)) 11635e96a66cSDavid du Colombier goto Err; 11645e96a66cSDavid du Colombier if(mb.nindex > 0){ 11655e96a66cSDavid du Colombier vtSetError(ENotEmpty); 11665e96a66cSDavid du Colombier goto Err; 11675e96a66cSDavid du Colombier } 11685e96a66cSDavid du Colombier blockPut(b); 11695e96a66cSDavid du Colombier } 11705e96a66cSDavid du Colombier return 1; 11715e96a66cSDavid du Colombier Err: 11725e96a66cSDavid du Colombier blockPut(b); 11735e96a66cSDavid du Colombier return 0; 11745e96a66cSDavid du Colombier } 11755e96a66cSDavid du Colombier 11765e96a66cSDavid du Colombier int 11775e96a66cSDavid du Colombier fileRemove(File *f, char *uid) 11785e96a66cSDavid du Colombier { 11795e96a66cSDavid du Colombier File *ff; 11805e96a66cSDavid du Colombier 11815e96a66cSDavid du Colombier /* can not remove the root */ 11825e96a66cSDavid du Colombier if(fileIsRoot(f)){ 11835e96a66cSDavid du Colombier vtSetError(ERoot); 11845e96a66cSDavid du Colombier return 0; 11855e96a66cSDavid du Colombier } 11865e96a66cSDavid du Colombier 11875e96a66cSDavid du Colombier if(!fileLock(f)) 11885e96a66cSDavid du Colombier return 0; 11895e96a66cSDavid du Colombier 11905e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 11915e96a66cSDavid du Colombier vtSetError(EReadOnly); 11925e96a66cSDavid du Colombier goto Err1; 11935e96a66cSDavid du Colombier } 11945e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 11955e96a66cSDavid du Colombier goto Err1; 11965e96a66cSDavid du Colombier if(fileIsDir(f) && !fileCheckEmpty(f)) 11975e96a66cSDavid du Colombier goto Err; 11985e96a66cSDavid du Colombier 11995e96a66cSDavid du Colombier for(ff=f->down; ff; ff=ff->next) 12005e96a66cSDavid du Colombier assert(ff->removed); 12015e96a66cSDavid du Colombier 12025e96a66cSDavid du Colombier sourceRemove(f->source); 12035e96a66cSDavid du Colombier f->source = nil; 12045e96a66cSDavid du Colombier if(f->msource){ 12055e96a66cSDavid du Colombier sourceRemove(f->msource); 12065e96a66cSDavid du Colombier f->msource = nil; 12075e96a66cSDavid du Colombier } 12085e96a66cSDavid du Colombier 12095e96a66cSDavid du Colombier fileUnlock(f); 12105e96a66cSDavid du Colombier 12115e96a66cSDavid du Colombier if(!fileMetaRemove(f, uid)) 12125e96a66cSDavid du Colombier return 0; 12135e96a66cSDavid du Colombier 12145e96a66cSDavid du Colombier return 1; 12155e96a66cSDavid du Colombier 12165e96a66cSDavid du Colombier Err: 12175e96a66cSDavid du Colombier sourceUnlock(f->source); 12185e96a66cSDavid du Colombier if(f->msource) 12195e96a66cSDavid du Colombier sourceUnlock(f->msource); 12205e96a66cSDavid du Colombier Err1: 12215e96a66cSDavid du Colombier fileUnlock(f); 12225e96a66cSDavid du Colombier return 0; 12235e96a66cSDavid du Colombier } 12245e96a66cSDavid du Colombier 1225dc5a79c1SDavid du Colombier static int 1226dc5a79c1SDavid du Colombier clri(File *f, char *uid) 12275e96a66cSDavid du Colombier { 12285e96a66cSDavid du Colombier int r; 12295e96a66cSDavid du Colombier 12305e96a66cSDavid du Colombier if(f == nil) 12315e96a66cSDavid du Colombier return 0; 12325e96a66cSDavid du Colombier if(f->up->source->mode != OReadWrite){ 12335e96a66cSDavid du Colombier vtSetError(EReadOnly); 12345e96a66cSDavid du Colombier fileDecRef(f); 12355e96a66cSDavid du Colombier return 0; 12365e96a66cSDavid du Colombier } 12375e96a66cSDavid du Colombier r = fileMetaRemove(f, uid); 12385e96a66cSDavid du Colombier fileDecRef(f); 12395e96a66cSDavid du Colombier return r; 12405e96a66cSDavid du Colombier } 12415e96a66cSDavid du Colombier 1242dc5a79c1SDavid du Colombier int 1243dc5a79c1SDavid du Colombier fileClriPath(Fs *fs, char *path, char *uid) 1244dc5a79c1SDavid du Colombier { 1245dc5a79c1SDavid du Colombier return clri(_fileOpen(fs, path, 1), uid); 1246dc5a79c1SDavid du Colombier } 1247dc5a79c1SDavid du Colombier 1248dc5a79c1SDavid du Colombier int 1249dc5a79c1SDavid du Colombier fileClri(File *dir, char *elem, char *uid) 1250dc5a79c1SDavid du Colombier { 1251dc5a79c1SDavid du Colombier return clri(_fileWalk(dir, elem, 1), uid); 1252dc5a79c1SDavid du Colombier } 1253dc5a79c1SDavid du Colombier 12545e96a66cSDavid du Colombier File * 12555e96a66cSDavid du Colombier fileIncRef(File *vf) 12565e96a66cSDavid du Colombier { 12575e96a66cSDavid du Colombier fileMetaLock(vf); 12585e96a66cSDavid du Colombier assert(vf->ref > 0); 12595e96a66cSDavid du Colombier vf->ref++; 12605e96a66cSDavid du Colombier fileMetaUnlock(vf); 12615e96a66cSDavid du Colombier return vf; 12625e96a66cSDavid du Colombier } 12635e96a66cSDavid du Colombier 12645e96a66cSDavid du Colombier int 12655e96a66cSDavid du Colombier fileDecRef(File *f) 12665e96a66cSDavid du Colombier { 12675e96a66cSDavid du Colombier File *p, *q, **qq; 12685e96a66cSDavid du Colombier 12695e96a66cSDavid du Colombier if(f->up == nil){ 12705e96a66cSDavid du Colombier /* never linked in */ 12715e96a66cSDavid du Colombier assert(f->ref == 1); 12725e96a66cSDavid du Colombier fileFree(f); 12735e96a66cSDavid du Colombier return 1; 12745e96a66cSDavid du Colombier } 12755e96a66cSDavid du Colombier 12765e96a66cSDavid du Colombier fileMetaLock(f); 12775e96a66cSDavid du Colombier f->ref--; 12785e96a66cSDavid du Colombier if(f->ref > 0){ 12795e96a66cSDavid du Colombier fileMetaUnlock(f); 12805e96a66cSDavid du Colombier return 0; 12815e96a66cSDavid du Colombier } 12825e96a66cSDavid du Colombier assert(f->ref == 0); 12835e96a66cSDavid du Colombier assert(f->down == nil); 12845e96a66cSDavid du Colombier 12855e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 12865e96a66cSDavid du Colombier 12875e96a66cSDavid du Colombier p = f->up; 12885e96a66cSDavid du Colombier qq = &p->down; 12895e96a66cSDavid du Colombier for(q = *qq; q; q = *qq){ 12905e96a66cSDavid du Colombier if(q == f) 12915e96a66cSDavid du Colombier break; 12925e96a66cSDavid du Colombier qq = &q->next; 12935e96a66cSDavid du Colombier } 12945e96a66cSDavid du Colombier assert(q != nil); 12955e96a66cSDavid du Colombier *qq = f->next; 12965e96a66cSDavid du Colombier 12975e96a66cSDavid du Colombier fileMetaUnlock(f); 12985e96a66cSDavid du Colombier fileFree(f); 12995e96a66cSDavid du Colombier 13005e96a66cSDavid du Colombier fileDecRef(p); 13015e96a66cSDavid du Colombier return 1; 13025e96a66cSDavid du Colombier } 13035e96a66cSDavid du Colombier 13045e96a66cSDavid du Colombier File * 13055e96a66cSDavid du Colombier fileGetParent(File *f) 13065e96a66cSDavid du Colombier { 13075e96a66cSDavid du Colombier if(fileIsRoot(f)) 13085e96a66cSDavid du Colombier return fileIncRef(f); 13095e96a66cSDavid du Colombier return fileIncRef(f->up); 13105e96a66cSDavid du Colombier } 13115e96a66cSDavid du Colombier 13125e96a66cSDavid du Colombier DirEntryEnum * 13135e96a66cSDavid du Colombier deeOpen(File *f) 13145e96a66cSDavid du Colombier { 13155e96a66cSDavid du Colombier DirEntryEnum *dee; 13165e96a66cSDavid du Colombier File *p; 13175e96a66cSDavid du Colombier 13185e96a66cSDavid du Colombier if(!fileIsDir(f)){ 13195e96a66cSDavid du Colombier vtSetError(ENotDir); 13205e96a66cSDavid du Colombier fileDecRef(f); 13215e96a66cSDavid du Colombier return nil; 13225e96a66cSDavid du Colombier } 13235e96a66cSDavid du Colombier 13245e96a66cSDavid du Colombier /* flush out meta data */ 13255e96a66cSDavid du Colombier if(!fileLock(f)) 13265e96a66cSDavid du Colombier return nil; 13275e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 13285e96a66cSDavid du Colombier fileMetaFlush2(p, nil); 13295e96a66cSDavid du Colombier fileUnlock(f); 13305e96a66cSDavid du Colombier 13315e96a66cSDavid du Colombier dee = vtMemAllocZ(sizeof(DirEntryEnum)); 13325e96a66cSDavid du Colombier dee->file = fileIncRef(f); 13335e96a66cSDavid du Colombier 13345e96a66cSDavid du Colombier return dee; 13355e96a66cSDavid du Colombier } 13365e96a66cSDavid du Colombier 13375e96a66cSDavid du Colombier static int 13385e96a66cSDavid du Colombier dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size) 13395e96a66cSDavid du Colombier { 13405e96a66cSDavid du Colombier Block *b; 13415e96a66cSDavid du Colombier ulong bn; 13425e96a66cSDavid du Colombier Entry e; 13435e96a66cSDavid du Colombier int epb; 13445e96a66cSDavid du Colombier 13455e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 13465e96a66cSDavid du Colombier bn = elem/epb; 13475e96a66cSDavid du Colombier elem -= bn*epb; 13485e96a66cSDavid du Colombier 13495e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 13505e96a66cSDavid du Colombier if(b == nil) 13515e96a66cSDavid du Colombier goto Err; 13525e96a66cSDavid du Colombier if(!entryUnpack(&e, b->data, elem)) 13535e96a66cSDavid du Colombier goto Err; 13545e96a66cSDavid du Colombier 13555e96a66cSDavid du Colombier /* hanging entries are returned as zero size */ 13565e96a66cSDavid du Colombier if(!(e.flags & VtEntryActive) || e.gen != gen) 13575e96a66cSDavid du Colombier *size = 0; 13585e96a66cSDavid du Colombier else 13595e96a66cSDavid du Colombier *size = e.size; 13605e96a66cSDavid du Colombier blockPut(b); 13615e96a66cSDavid du Colombier return 1; 13625e96a66cSDavid du Colombier 13635e96a66cSDavid du Colombier Err: 13645e96a66cSDavid du Colombier blockPut(b); 13655e96a66cSDavid du Colombier return 0; 13665e96a66cSDavid du Colombier } 13675e96a66cSDavid du Colombier 13685e96a66cSDavid du Colombier static int 13695e96a66cSDavid du Colombier deeFill(DirEntryEnum *dee) 13705e96a66cSDavid du Colombier { 13715e96a66cSDavid du Colombier int i, n; 13725e96a66cSDavid du Colombier Source *meta, *source; 13735e96a66cSDavid du Colombier MetaBlock mb; 13745e96a66cSDavid du Colombier MetaEntry me; 13755e96a66cSDavid du Colombier File *f; 13765e96a66cSDavid du Colombier Block *b; 13775e96a66cSDavid du Colombier DirEntry *de; 13785e96a66cSDavid du Colombier 13795e96a66cSDavid du Colombier /* clean up first */ 13805e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 13815e96a66cSDavid du Colombier deCleanup(dee->buf+i); 13825e96a66cSDavid du Colombier vtMemFree(dee->buf); 13835e96a66cSDavid du Colombier dee->buf = nil; 13845e96a66cSDavid du Colombier dee->i = 0; 13855e96a66cSDavid du Colombier dee->n = 0; 13865e96a66cSDavid du Colombier 13875e96a66cSDavid du Colombier f = dee->file; 13885e96a66cSDavid du Colombier 13895e96a66cSDavid du Colombier source = f->source; 13905e96a66cSDavid du Colombier meta = f->msource; 13915e96a66cSDavid du Colombier 13925e96a66cSDavid du Colombier b = sourceBlock(meta, dee->boff, OReadOnly); 13935e96a66cSDavid du Colombier if(b == nil) 13945e96a66cSDavid du Colombier goto Err; 13955e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 13965e96a66cSDavid du Colombier goto Err; 13975e96a66cSDavid du Colombier 13985e96a66cSDavid du Colombier n = mb.nindex; 13995e96a66cSDavid du Colombier dee->buf = vtMemAlloc(n * sizeof(DirEntry)); 14005e96a66cSDavid du Colombier 14015e96a66cSDavid du Colombier for(i=0; i<n; i++){ 14025e96a66cSDavid du Colombier de = dee->buf + i; 14035e96a66cSDavid du Colombier meUnpack(&me, &mb, i); 14045e96a66cSDavid du Colombier if(!deUnpack(de, &me)) 14055e96a66cSDavid du Colombier goto Err; 14065e96a66cSDavid du Colombier dee->n++; 14075e96a66cSDavid du Colombier if(!(de->mode & ModeDir)) 14085e96a66cSDavid du Colombier if(!dirEntrySize(source, de->entry, de->gen, &de->size)) 14095e96a66cSDavid du Colombier goto Err; 14105e96a66cSDavid du Colombier } 14115e96a66cSDavid du Colombier dee->boff++; 14125e96a66cSDavid du Colombier blockPut(b); 14135e96a66cSDavid du Colombier return 1; 14145e96a66cSDavid du Colombier Err: 14155e96a66cSDavid du Colombier blockPut(b); 14165e96a66cSDavid du Colombier return 0; 14175e96a66cSDavid du Colombier } 14185e96a66cSDavid du Colombier 14195e96a66cSDavid du Colombier int 14205e96a66cSDavid du Colombier deeRead(DirEntryEnum *dee, DirEntry *de) 14215e96a66cSDavid du Colombier { 14225e96a66cSDavid du Colombier int ret, didread; 14235e96a66cSDavid du Colombier File *f; 14245e96a66cSDavid du Colombier u32int nb; 14255e96a66cSDavid du Colombier 14265e96a66cSDavid du Colombier f = dee->file; 14275e96a66cSDavid du Colombier if(!fileRLock(f)) 14285e96a66cSDavid du Colombier return -1; 14295e96a66cSDavid du Colombier 14305e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadOnly)){ 14315e96a66cSDavid du Colombier fileRUnlock(f); 14325e96a66cSDavid du Colombier return -1; 14335e96a66cSDavid du Colombier } 14345e96a66cSDavid du Colombier 14355e96a66cSDavid du Colombier nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize; 14365e96a66cSDavid du Colombier 14375e96a66cSDavid du Colombier didread = 0; 14385e96a66cSDavid du Colombier while(dee->i >= dee->n){ 14395e96a66cSDavid du Colombier if(dee->boff >= nb){ 14405e96a66cSDavid du Colombier ret = 0; 14415e96a66cSDavid du Colombier goto Return; 14425e96a66cSDavid du Colombier } 14435e96a66cSDavid du Colombier didread = 1; 14445e96a66cSDavid du Colombier if(!deeFill(dee)){ 14455e96a66cSDavid du Colombier ret = -1; 14465e96a66cSDavid du Colombier goto Return; 14475e96a66cSDavid du Colombier } 14485e96a66cSDavid du Colombier } 14495e96a66cSDavid du Colombier 14505e96a66cSDavid du Colombier memmove(de, dee->buf + dee->i, sizeof(DirEntry)); 14515e96a66cSDavid du Colombier dee->i++; 14525e96a66cSDavid du Colombier ret = 1; 14535e96a66cSDavid du Colombier 14545e96a66cSDavid du Colombier Return: 14555e96a66cSDavid du Colombier sourceUnlock(f->source); 14565e96a66cSDavid du Colombier sourceUnlock(f->msource); 14575e96a66cSDavid du Colombier fileRUnlock(f); 14585e96a66cSDavid du Colombier 14595e96a66cSDavid du Colombier if(didread) 14605e96a66cSDavid du Colombier fileRAccess(f); 14615e96a66cSDavid du Colombier return ret; 14625e96a66cSDavid du Colombier } 14635e96a66cSDavid du Colombier 14645e96a66cSDavid du Colombier void 14655e96a66cSDavid du Colombier deeClose(DirEntryEnum *dee) 14665e96a66cSDavid du Colombier { 14675e96a66cSDavid du Colombier int i; 14685e96a66cSDavid du Colombier if(dee == nil) 14695e96a66cSDavid du Colombier return; 14705e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 14715e96a66cSDavid du Colombier deCleanup(dee->buf+i); 14725e96a66cSDavid du Colombier vtMemFree(dee->buf); 14735e96a66cSDavid du Colombier fileDecRef(dee->file); 14745e96a66cSDavid du Colombier vtMemFree(dee); 14755e96a66cSDavid du Colombier } 14765e96a66cSDavid du Colombier 14775e96a66cSDavid du Colombier /* 14785e96a66cSDavid du Colombier * caller must lock f->source and f->msource 14795e96a66cSDavid du Colombier * caller must NOT lock the source and msource 14805e96a66cSDavid du Colombier * referenced by dir. 14815e96a66cSDavid du Colombier */ 14825e96a66cSDavid du Colombier static u32int 14835e96a66cSDavid du Colombier fileMetaAlloc(File *f, DirEntry *dir, u32int start) 14845e96a66cSDavid du Colombier { 14855e96a66cSDavid du Colombier u32int nb, bo; 14865e96a66cSDavid du Colombier Block *b, *bb; 14875e96a66cSDavid du Colombier MetaBlock mb; 14885e96a66cSDavid du Colombier int nn; 14895e96a66cSDavid du Colombier uchar *p; 14905e96a66cSDavid du Colombier int i, n, epb; 14915e96a66cSDavid du Colombier MetaEntry me; 14925e96a66cSDavid du Colombier Source *s, *ms; 14935e96a66cSDavid du Colombier 14945e96a66cSDavid du Colombier s = f->source; 14955e96a66cSDavid du Colombier ms = f->msource; 14965e96a66cSDavid du Colombier 14975e96a66cSDavid du Colombier n = deSize(dir); 14985e96a66cSDavid du Colombier nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize; 14995e96a66cSDavid du Colombier b = nil; 15005e96a66cSDavid du Colombier if(start > nb) 15015e96a66cSDavid du Colombier start = nb; 15025e96a66cSDavid du Colombier for(bo=start; bo<nb; bo++){ 15035e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 15045e96a66cSDavid du Colombier if(b == nil) 15055e96a66cSDavid du Colombier goto Err; 15065e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, ms->dsize)) 15075e96a66cSDavid du Colombier goto Err; 15085e96a66cSDavid du Colombier nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free; 15095e96a66cSDavid du Colombier if(n <= nn && mb.nindex < mb.maxindex) 15105e96a66cSDavid du Colombier break; 15115e96a66cSDavid du Colombier blockPut(b); 15125e96a66cSDavid du Colombier b = nil; 15135e96a66cSDavid du Colombier } 15145e96a66cSDavid du Colombier 15155e96a66cSDavid du Colombier /* add block to meta file */ 15165e96a66cSDavid du Colombier if(b == nil){ 15175e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 15185e96a66cSDavid du Colombier if(b == nil) 15195e96a66cSDavid du Colombier goto Err; 15205e96a66cSDavid du Colombier sourceSetSize(ms, (nb+1)*ms->dsize); 15215e96a66cSDavid du Colombier mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry); 15225e96a66cSDavid du Colombier } 15235e96a66cSDavid du Colombier 15245e96a66cSDavid du Colombier p = mbAlloc(&mb, n); 15255e96a66cSDavid du Colombier if(p == nil){ 15265e96a66cSDavid du Colombier /* mbAlloc might have changed block */ 15275e96a66cSDavid du Colombier mbPack(&mb); 15285e96a66cSDavid du Colombier blockDirty(b); 15295e96a66cSDavid du Colombier vtSetError(EBadMeta); 15305e96a66cSDavid du Colombier goto Err; 15315e96a66cSDavid du Colombier } 15325e96a66cSDavid du Colombier 15335e96a66cSDavid du Colombier mbSearch(&mb, dir->elem, &i, &me); 15345e96a66cSDavid du Colombier assert(me.p == nil); 15355e96a66cSDavid du Colombier me.p = p; 15365e96a66cSDavid du Colombier me.size = n; 15375e96a66cSDavid du Colombier dePack(dir, &me); 15385e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 15395e96a66cSDavid du Colombier mbPack(&mb); 15405e96a66cSDavid du Colombier 15415e96a66cSDavid du Colombier /* meta block depends on super block for qid ... */ 15425e96a66cSDavid du Colombier bb = cacheLocal(b->c, PartSuper, 0, OReadOnly); 154361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15445e96a66cSDavid du Colombier blockPut(bb); 15455e96a66cSDavid du Colombier 15465e96a66cSDavid du Colombier /* ... and one or two dir entries */ 15475e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 15485e96a66cSDavid du Colombier bb = sourceBlock(s, dir->entry/epb, OReadOnly); 154961201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15505e96a66cSDavid du Colombier blockPut(bb); 15515e96a66cSDavid du Colombier if(dir->mode & ModeDir){ 15525e96a66cSDavid du Colombier bb = sourceBlock(s, dir->mentry/epb, OReadOnly); 155361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 15545e96a66cSDavid du Colombier blockPut(bb); 15555e96a66cSDavid du Colombier } 15565e96a66cSDavid du Colombier 15575e96a66cSDavid du Colombier blockDirty(b); 15585e96a66cSDavid du Colombier blockPut(b); 15595e96a66cSDavid du Colombier return bo; 15605e96a66cSDavid du Colombier Err: 15615e96a66cSDavid du Colombier blockPut(b); 15625e96a66cSDavid du Colombier return NilBlock; 15635e96a66cSDavid du Colombier } 15645e96a66cSDavid du Colombier 15655e96a66cSDavid du Colombier static int 15665e96a66cSDavid du Colombier chkSource(File *f) 15675e96a66cSDavid du Colombier { 15685e96a66cSDavid du Colombier if(f->partial) 15695e96a66cSDavid du Colombier return 1; 15705e96a66cSDavid du Colombier 15715e96a66cSDavid du Colombier if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){ 15725e96a66cSDavid du Colombier vtSetError(ERemoved); 15735e96a66cSDavid du Colombier return 0; 15745e96a66cSDavid du Colombier } 15755e96a66cSDavid du Colombier return 1; 15765e96a66cSDavid du Colombier } 15775e96a66cSDavid du Colombier 15785e96a66cSDavid du Colombier static int 15795e96a66cSDavid du Colombier fileRLock(File *f) 15805e96a66cSDavid du Colombier { 15815e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 15825e96a66cSDavid du Colombier vtRLock(f->lk); 15835e96a66cSDavid du Colombier if(!chkSource(f)){ 15845e96a66cSDavid du Colombier fileRUnlock(f); 15855e96a66cSDavid du Colombier return 0; 15865e96a66cSDavid du Colombier } 15875e96a66cSDavid du Colombier return 1; 15885e96a66cSDavid du Colombier } 15895e96a66cSDavid du Colombier 15905e96a66cSDavid du Colombier static void 15915e96a66cSDavid du Colombier fileRUnlock(File *f) 15925e96a66cSDavid du Colombier { 15935e96a66cSDavid du Colombier vtRUnlock(f->lk); 15945e96a66cSDavid du Colombier } 15955e96a66cSDavid du Colombier 15965e96a66cSDavid du Colombier static int 15975e96a66cSDavid du Colombier fileLock(File *f) 15985e96a66cSDavid du Colombier { 15995e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 16005e96a66cSDavid du Colombier vtLock(f->lk); 16015e96a66cSDavid du Colombier if(!chkSource(f)){ 16025e96a66cSDavid du Colombier fileUnlock(f); 16035e96a66cSDavid du Colombier return 0; 16045e96a66cSDavid du Colombier } 16055e96a66cSDavid du Colombier return 1; 16065e96a66cSDavid du Colombier } 16075e96a66cSDavid du Colombier 16085e96a66cSDavid du Colombier static void 16095e96a66cSDavid du Colombier fileUnlock(File *f) 16105e96a66cSDavid du Colombier { 16115e96a66cSDavid du Colombier vtUnlock(f->lk); 16125e96a66cSDavid du Colombier } 16135e96a66cSDavid du Colombier 16145e96a66cSDavid du Colombier /* 16155e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16165e96a66cSDavid du Colombier * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2). 16175e96a66cSDavid du Colombier * We have to respect that ordering. 16185e96a66cSDavid du Colombier */ 16195e96a66cSDavid du Colombier static void 16205e96a66cSDavid du Colombier fileMetaLock(File *f) 16215e96a66cSDavid du Colombier { 16225e96a66cSDavid du Colombier if(f->up == nil) 16235e96a66cSDavid du Colombier fprint(2, "f->elem = %s\n", f->dir.elem); 16245e96a66cSDavid du Colombier assert(f->up != nil); 16255e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 16265e96a66cSDavid du Colombier vtLock(f->up->lk); 16275e96a66cSDavid du Colombier } 16285e96a66cSDavid du Colombier 16295e96a66cSDavid du Colombier static void 16305e96a66cSDavid du Colombier fileMetaUnlock(File *f) 16315e96a66cSDavid du Colombier { 16325e96a66cSDavid du Colombier vtUnlock(f->up->lk); 16335e96a66cSDavid du Colombier } 16345e96a66cSDavid du Colombier 16355e96a66cSDavid du Colombier /* 16365e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16375e96a66cSDavid du Colombier * see fileMetaLock. 16385e96a66cSDavid du Colombier */ 16395e96a66cSDavid du Colombier static void 16405e96a66cSDavid du Colombier fileRAccess(File* f) 16415e96a66cSDavid du Colombier { 16425e96a66cSDavid du Colombier if(f->mode == OReadOnly) 16435e96a66cSDavid du Colombier return; 16445e96a66cSDavid du Colombier 16455e96a66cSDavid du Colombier fileMetaLock(f); 16465e96a66cSDavid du Colombier f->dir.atime = time(0L); 16475e96a66cSDavid du Colombier f->dirty = 1; 16485e96a66cSDavid du Colombier fileMetaUnlock(f); 16495e96a66cSDavid du Colombier } 16505e96a66cSDavid du Colombier 16515e96a66cSDavid du Colombier /* 16525e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 16535e96a66cSDavid du Colombier * see fileMetaLock. 16545e96a66cSDavid du Colombier */ 16555e96a66cSDavid du Colombier static void 16565e96a66cSDavid du Colombier fileWAccess(File* f, char *mid) 16575e96a66cSDavid du Colombier { 16585e96a66cSDavid du Colombier if(f->mode == OReadOnly) 16595e96a66cSDavid du Colombier return; 16605e96a66cSDavid du Colombier 16615e96a66cSDavid du Colombier fileMetaLock(f); 16625e96a66cSDavid du Colombier f->dir.atime = f->dir.mtime = time(0L); 16635e96a66cSDavid du Colombier if(strcmp(f->dir.mid, mid) != 0){ 16645e96a66cSDavid du Colombier vtMemFree(f->dir.mid); 16655e96a66cSDavid du Colombier f->dir.mid = vtStrDup(mid); 16665e96a66cSDavid du Colombier } 16675e96a66cSDavid du Colombier f->dir.mcount++; 16685e96a66cSDavid du Colombier f->dirty = 1; 16695e96a66cSDavid du Colombier fileMetaUnlock(f); 1670d58da526SDavid du Colombier 1671d58da526SDavid du Colombier /*RSC: let's try this */ 1672d58da526SDavid du Colombier /*presotto - lets not 1673d58da526SDavid du Colombier if(f->up) 1674d58da526SDavid du Colombier fileWAccess(f->up, mid); 1675d58da526SDavid du Colombier */ 16765e96a66cSDavid du Colombier } 16775e96a66cSDavid du Colombier 16785e96a66cSDavid du Colombier static void 16795e96a66cSDavid du Colombier markCopied(Block *b) 16805e96a66cSDavid du Colombier { 16815e96a66cSDavid du Colombier Block *lb; 16825e96a66cSDavid du Colombier Label l; 16835e96a66cSDavid du Colombier 16845e96a66cSDavid du Colombier if(globalToLocal(b->score) == NilBlock) 16855e96a66cSDavid du Colombier return; 16865e96a66cSDavid du Colombier 16875e96a66cSDavid du Colombier if(!(b->l.state & BsCopied)){ 16885e96a66cSDavid du Colombier /* 16895e96a66cSDavid du Colombier * We need to record that there are now pointers in 16905e96a66cSDavid du Colombier * b that are not unique to b. We do this by marking 16915e96a66cSDavid du Colombier * b as copied. Since we don't return the label block, 16925e96a66cSDavid du Colombier * the caller can't get the dependencies right. So we have 16935e96a66cSDavid du Colombier * to flush the block ourselves. This is a rare occurrence. 16945e96a66cSDavid du Colombier */ 16955e96a66cSDavid du Colombier l = b->l; 16965e96a66cSDavid du Colombier l.state |= BsCopied; 16975e96a66cSDavid du Colombier lb = _blockSetLabel(b, &l); 16985e96a66cSDavid du Colombier WriteAgain: 16995e96a66cSDavid du Colombier while(!blockWrite(lb)){ 17005e96a66cSDavid du Colombier fprint(2, "getEntry: could not write label block\n"); 17015e96a66cSDavid du Colombier sleep(10*1000); 17025e96a66cSDavid du Colombier } 17035e96a66cSDavid du Colombier while(lb->iostate != BioClean && lb->iostate != BioDirty){ 17045e96a66cSDavid du Colombier assert(lb->iostate == BioWriting); 17055e96a66cSDavid du Colombier vtSleep(lb->ioready); 17065e96a66cSDavid du Colombier } 17075e96a66cSDavid du Colombier if(lb->iostate == BioDirty) 17085e96a66cSDavid du Colombier goto WriteAgain; 17095e96a66cSDavid du Colombier blockPut(lb); 17105e96a66cSDavid du Colombier } 17115e96a66cSDavid du Colombier } 17125e96a66cSDavid du Colombier 17135e96a66cSDavid du Colombier static int 17145e96a66cSDavid du Colombier getEntry(Source *r, Entry *e, int mark) 17155e96a66cSDavid du Colombier { 17165e96a66cSDavid du Colombier Block *b; 17175e96a66cSDavid du Colombier 17185e96a66cSDavid du Colombier if(r == nil){ 17195e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 17205e96a66cSDavid du Colombier return 1; 17215e96a66cSDavid du Colombier } 17225e96a66cSDavid du Colombier 17235e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly); 17245e96a66cSDavid du Colombier if(b == nil) 17255e96a66cSDavid du Colombier return 0; 17265e96a66cSDavid du Colombier if(!entryUnpack(e, b->data, r->offset % r->epb)){ 17275e96a66cSDavid du Colombier blockPut(b); 17285e96a66cSDavid du Colombier return 0; 17295e96a66cSDavid du Colombier } 17305e96a66cSDavid du Colombier 17315e96a66cSDavid du Colombier if(mark) 17325e96a66cSDavid du Colombier markCopied(b); 17335e96a66cSDavid du Colombier blockPut(b); 17345e96a66cSDavid du Colombier return 1; 17355e96a66cSDavid du Colombier } 17365e96a66cSDavid du Colombier 17375e96a66cSDavid du Colombier static int 17385e96a66cSDavid du Colombier setEntry(Source *r, Entry *e) 17395e96a66cSDavid du Colombier { 17405e96a66cSDavid du Colombier Block *b; 17415e96a66cSDavid du Colombier Entry oe; 17425e96a66cSDavid du Colombier 17435e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite); 17445e96a66cSDavid du Colombier if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score); 17455e96a66cSDavid du Colombier if(b == nil) 17465e96a66cSDavid du Colombier return 0; 17475e96a66cSDavid du Colombier if(!entryUnpack(&oe, b->data, r->offset % r->epb)){ 17485e96a66cSDavid du Colombier blockPut(b); 17495e96a66cSDavid du Colombier return 0; 17505e96a66cSDavid du Colombier } 17515e96a66cSDavid du Colombier e->gen = oe.gen; 17525e96a66cSDavid du Colombier entryPack(e, b->data, r->offset % r->epb); 17535e96a66cSDavid du Colombier 17545e96a66cSDavid du Colombier /* BUG b should depend on the entry pointer */ 17555e96a66cSDavid du Colombier 17565e96a66cSDavid du Colombier markCopied(b); 17575e96a66cSDavid du Colombier blockDirty(b); 17585e96a66cSDavid du Colombier blockPut(b); 17595e96a66cSDavid du Colombier return 1; 17605e96a66cSDavid du Colombier } 17615e96a66cSDavid du Colombier 17625e96a66cSDavid du Colombier /* assumes hold elk */ 17635e96a66cSDavid du Colombier int 17645e96a66cSDavid du Colombier fileSnapshot(File *dst, File *src, u32int epoch, int doarchive) 17655e96a66cSDavid du Colombier { 17665e96a66cSDavid du Colombier Entry e, ee; 17675e96a66cSDavid du Colombier 17685e96a66cSDavid du Colombier /* add link to snapshot */ 17695e96a66cSDavid du Colombier if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1)) 17705e96a66cSDavid du Colombier return 0; 17715e96a66cSDavid du Colombier 17725e96a66cSDavid du Colombier e.snap = epoch; 17735e96a66cSDavid du Colombier e.archive = doarchive; 17745e96a66cSDavid du Colombier ee.snap = epoch; 17755e96a66cSDavid du Colombier ee.archive = doarchive; 17765e96a66cSDavid du Colombier 17775e96a66cSDavid du Colombier if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee)) 17785e96a66cSDavid du Colombier return 0; 17795e96a66cSDavid du Colombier return 1; 17805e96a66cSDavid du Colombier } 17815e96a66cSDavid du Colombier 17825e96a66cSDavid du Colombier int 17835e96a66cSDavid du Colombier fileGetSources(File *f, Entry *e, Entry *ee, int mark) 17845e96a66cSDavid du Colombier { 17855e96a66cSDavid du Colombier if(!getEntry(f->source, e, mark) 17865e96a66cSDavid du Colombier || !getEntry(f->msource, ee, mark)) 17875e96a66cSDavid du Colombier return 0; 17885e96a66cSDavid du Colombier return 1; 17895e96a66cSDavid du Colombier } 17905e96a66cSDavid du Colombier 17915e96a66cSDavid du Colombier int 17925e96a66cSDavid du Colombier fileWalkSources(File *f) 17935e96a66cSDavid du Colombier { 17945e96a66cSDavid du Colombier if(f->mode == OReadOnly) 17955e96a66cSDavid du Colombier return 1; 17965e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadWrite)) 17975e96a66cSDavid du Colombier return 0; 17985e96a66cSDavid du Colombier sourceUnlock(f->source); 17995e96a66cSDavid du Colombier sourceUnlock(f->msource); 18005e96a66cSDavid du Colombier return 1; 18015e96a66cSDavid du Colombier } 1802