1 #include "lib9.h" 2 #include "logfs.h" 3 #include "local.h" 4 5 void 6 logfsfreeanddirtydatablockcheck(LogfsServer *server, long seq) 7 { 8 DataBlock *db; 9 u32int mask; 10 11 if(seq >= server->ndatablocks) 12 return; 13 db = server->datablock + seq; 14 if(db->block < 0) 15 return; 16 17 mask = db->dirty & db->free; 18 if(mask) { 19 u32int allpages = logfsdatapagemask(1 << server->ll->l2pagesperblock, 0); 20 if((mask & allpages) == allpages) { 21 //print("logfsfreedatapages: returning block to the wild\n"); 22 logfsbootfettleblock(server->lb, db->block, LogfsTnone, ~0, nil); 23 db->block = -1; 24 if(seq == server->ndatablocks - 1) 25 server->ndatablocks--; 26 } 27 } 28 } 29 30 void 31 logfsfreedatapages(LogfsServer *server, long seq, u32int mask) 32 { 33 DataBlock *db; 34 if(seq >= server->ndatablocks) 35 return; 36 db = server->datablock + seq; 37 if(db->block < 0) 38 return; 39 //print("logfsfreedatapages: index %ld mask 0x%.8ux\n", seq, mask); 40 db->dirty |= mask; 41 db->free |= mask; 42 logfsfreeanddirtydatablockcheck(server, seq); 43 } 44 45 int 46 logfsunconditionallymarkfreeanddirty(void *magic, Extent *e, int hole) 47 { 48 if(!hole && (e->flashaddr & LogAddr) == 0) { 49 LogfsServer *server = magic; 50 LogfsLowLevel *ll = server->ll; 51 DataBlock *db; 52 long blockindex; 53 int page, offset; 54 logfsflashaddr2spo(server, e->flashaddr, &blockindex, &page, &offset); 55 if(blockindex < server->ndatablocks && (db = server->datablock + blockindex)->block >= 0) { 56 int npages = ((offset + e->max - e->min) + (1 << ll->l2pagesize) - 1) >> ll->l2pagesize; 57 u32int mask = logfsdatapagemask(npages, page); 58 if((db->dirty & mask) != mask) 59 print("markfreeandirty: not all pages dirty\n"); 60 //print("markfreeanddirty: datablock %ld mask 0x%.8ux\n", blockindex, mask); 61 logfsfreedatapages(server, blockindex, mask); 62 } 63 else 64 print("markfreeanddirty: data block index %ld invalid\n", blockindex); 65 } 66 return 1; 67 } 68 69 char * 70 logfsserverremove(LogfsServer *server, u32int fid) 71 { 72 Fid *f; 73 char *errmsg; 74 Entry *parent; 75 Entry *e, **ep; 76 ulong now; 77 char *uid; 78 LogMessage s; 79 80 if(server->trace > 1) 81 print("logfsserverremove(%ud)\n", fid); 82 f = logfsfidmapfindentry(server->fidmap, fid); 83 if(f == nil) { 84 errmsg = logfsebadfid; 85 goto clunk; 86 } 87 if((f->openmode & 3) == OWRITE) { 88 errmsg = logfseaccess; 89 goto clunk; 90 } 91 parent = f->entry->parent; 92 if(parent == f->entry) { 93 errmsg = Eperm; 94 goto clunk; 95 } 96 if((parent->qid.type & QTDIR) == 0) { 97 errmsg = logfseinternal; 98 goto clunk; 99 } 100 if(!logfsuserpermcheck(server, parent, f, DMWRITE)) { 101 errmsg = Eperm; 102 goto clunk; 103 } 104 if((f->entry->qid.type & QTDIR) != 0 && f->entry->u.dir.list) { 105 errmsg = logfsenotempty; 106 goto clunk; 107 } 108 if(f->entry->deadandgone) { 109 errmsg = Eio; 110 goto clunk; 111 } 112 for(ep = &parent->u.dir.list; e = *ep; ep = &e->next) 113 if(e == f->entry) 114 break; 115 if(e == nil) { 116 errmsg = logfseinternal; 117 goto clunk; 118 } 119 now = logfsnow(); 120 uid = logfsisfindidfromname(server->is, f->uname); 121 /* log it */ 122 s.type = LogfsLogTremove; 123 s.path = e->qid.path; 124 s.u.remove.mtime = e->mtime; 125 s.u.remove.muid = e->muid; 126 errmsg = logfslog(server, 1, &s); 127 if(errmsg) 128 goto clunk; 129 parent->mtime = now; 130 parent->muid = uid; 131 logfspathmapdeleteentry(server->pathmap, e->qid.path); 132 *ep = e->next; /* so open can't find it */ 133 e->deadandgone = 1; /* so that other fids don't work any more */ 134 /* 135 * lose the storage now, as deadandgone will prevent access 136 */ 137 if((e->qid.type & QTDIR) == 0) { 138 logfsextentlistwalk(e->u.file.extent, logfsunconditionallymarkfreeanddirty, server); 139 logfsextentlistfree(&e->u.file.extent); 140 } 141 e->inuse--; /* so that the entryclunk removes the storage */ 142 errmsg = nil; 143 clunk: 144 logfsfidmapclunk(server->fidmap, fid); 145 return errmsg; 146 } 147 148