1 #include "stdinc.h" 2 3 #include "9.h" 4 5 static struct { 6 VtLock* lock; 7 8 Excl* head; 9 Excl* tail; 10 } ebox; 11 12 struct Excl { 13 Fsys* fsys; 14 uvlong path; 15 ulong time; 16 17 Excl* next; 18 Excl* prev; 19 }; 20 21 enum { 22 LifeTime = (5*60), 23 }; 24 25 int exclAlloc(Fid * fid)26exclAlloc(Fid* fid) 27 { 28 ulong t; 29 Excl *excl; 30 31 assert(fid->excl == nil); 32 33 t = time(0L); 34 vtLock(ebox.lock); 35 for(excl = ebox.head; excl != nil; excl = excl->next){ 36 if(excl->fsys != fid->fsys || excl->path != fid->qid.path) 37 continue; 38 /* 39 * Found it. 40 * Now, check if it's timed out. 41 * If not, return error, it's locked. 42 * If it has timed out, zap the old 43 * one and continue on to allocate a 44 * a new one. 45 */ 46 if(excl->time >= t){ 47 vtUnlock(ebox.lock); 48 vtSetError("exclusive lock"); 49 return 0; 50 } 51 excl->fsys = nil; 52 } 53 54 /* 55 * Not found or timed-out. 56 * Alloc a new one and initialise. 57 */ 58 excl = vtMemAllocZ(sizeof(Excl)); 59 excl->fsys = fid->fsys; 60 excl->path = fid->qid.path; 61 excl->time = t+LifeTime; 62 if(ebox.tail != nil){ 63 excl->prev = ebox.tail; 64 ebox.tail->next = excl; 65 } 66 else{ 67 ebox.head = excl; 68 excl->prev = nil; 69 } 70 ebox.tail = excl; 71 excl->next = nil; 72 vtUnlock(ebox.lock); 73 74 fid->excl = excl; 75 return 1; 76 } 77 78 int exclUpdate(Fid * fid)79exclUpdate(Fid* fid) 80 { 81 ulong t; 82 Excl *excl; 83 84 excl = fid->excl; 85 86 t = time(0L); 87 vtLock(ebox.lock); 88 if(excl->time < t || excl->fsys != fid->fsys){ 89 vtUnlock(ebox.lock); 90 vtSetError("exclusive lock broken"); 91 return 0; 92 } 93 excl->time = t+LifeTime; 94 vtUnlock(ebox.lock); 95 96 return 1; 97 } 98 99 void exclFree(Fid * fid)100exclFree(Fid* fid) 101 { 102 Excl *excl; 103 104 if((excl = fid->excl) == nil) 105 return; 106 fid->excl = nil; 107 108 vtLock(ebox.lock); 109 if(excl->prev != nil) 110 excl->prev->next = excl->next; 111 else 112 ebox.head = excl->next; 113 if(excl->next != nil) 114 excl->next->prev = excl->prev; 115 else 116 ebox.tail = excl->prev; 117 vtUnlock(ebox.lock); 118 119 vtMemFree(excl); 120 } 121 122 void exclInit(void)123exclInit(void) 124 { 125 ebox.lock = vtLockAlloc(); 126 } 127