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