Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro #include "dat.h"
3 6f4d00ee 2013-09-23 0intro #include "fns.h"
4 6f4d00ee 2013-09-23 0intro #include "error.h"
5 6f4d00ee 2013-09-23 0intro
6 6f4d00ee 2013-09-23 0intro static void fsMetaFlush(void *a);
7 6f4d00ee 2013-09-23 0intro static Snap *snapInit(Fs*);
8 6f4d00ee 2013-09-23 0intro static void snapClose(Snap*);
9 6f4d00ee 2013-09-23 0intro
10 6f4d00ee 2013-09-23 0intro Fs *
11 4b576658 2013-09-23 0intro fsOpen(char *file, VtConn *z, long ncache, int mode)
12 6f4d00ee 2013-09-23 0intro {
13 6f4d00ee 2013-09-23 0intro int fd, m;
14 6f4d00ee 2013-09-23 0intro uchar oscore[VtScoreSize];
15 6f4d00ee 2013-09-23 0intro Block *b, *bs;
16 6f4d00ee 2013-09-23 0intro Disk *disk;
17 6f4d00ee 2013-09-23 0intro Fs *fs;
18 6f4d00ee 2013-09-23 0intro Super super;
19 4b576658 2013-09-23 0intro char e[ERRMAX];
20 6f4d00ee 2013-09-23 0intro
21 6f4d00ee 2013-09-23 0intro switch(mode){
22 6f4d00ee 2013-09-23 0intro default:
23 4b576658 2013-09-23 0intro werrstr(EBadMode);
24 6f4d00ee 2013-09-23 0intro return nil;
25 6f4d00ee 2013-09-23 0intro case OReadOnly:
26 6f4d00ee 2013-09-23 0intro m = OREAD;
27 6f4d00ee 2013-09-23 0intro break;
28 6f4d00ee 2013-09-23 0intro case OReadWrite:
29 6f4d00ee 2013-09-23 0intro m = ORDWR;
30 6f4d00ee 2013-09-23 0intro break;
31 6f4d00ee 2013-09-23 0intro }
32 6f4d00ee 2013-09-23 0intro fd = open(file, m);
33 6f4d00ee 2013-09-23 0intro if(fd < 0){
34 4b576658 2013-09-23 0intro werrstr("open %s: %r", file);
35 6f4d00ee 2013-09-23 0intro return nil;
36 6f4d00ee 2013-09-23 0intro }
37 6f4d00ee 2013-09-23 0intro
38 6f4d00ee 2013-09-23 0intro bwatchInit();
39 6f4d00ee 2013-09-23 0intro disk = diskAlloc(fd);
40 6f4d00ee 2013-09-23 0intro if(disk == nil){
41 4b576658 2013-09-23 0intro werrstr("diskAlloc: %r");
42 6f4d00ee 2013-09-23 0intro close(fd);
43 6f4d00ee 2013-09-23 0intro return nil;
44 6f4d00ee 2013-09-23 0intro }
45 6f4d00ee 2013-09-23 0intro
46 4b576658 2013-09-23 0intro fs = vtmallocz(sizeof(Fs));
47 6f4d00ee 2013-09-23 0intro fs->mode = mode;
48 4b576658 2013-09-23 0intro fs->name = vtstrdup(file);
49 6f4d00ee 2013-09-23 0intro fs->blockSize = diskBlockSize(disk);
50 6f4d00ee 2013-09-23 0intro fs->cache = cacheAlloc(disk, z, ncache, mode);
51 6f4d00ee 2013-09-23 0intro if(mode == OReadWrite && z)
52 6f4d00ee 2013-09-23 0intro fs->arch = archInit(fs->cache, disk, fs, z);
53 6f4d00ee 2013-09-23 0intro fs->z = z;
54 6f4d00ee 2013-09-23 0intro
55 6f4d00ee 2013-09-23 0intro b = cacheLocal(fs->cache, PartSuper, 0, mode);
56 6f4d00ee 2013-09-23 0intro if(b == nil)
57 6f4d00ee 2013-09-23 0intro goto Err;
58 6f4d00ee 2013-09-23 0intro if(!superUnpack(&super, b->data)){
59 6f4d00ee 2013-09-23 0intro blockPut(b);
60 4b576658 2013-09-23 0intro werrstr("bad super block");
61 6f4d00ee 2013-09-23 0intro goto Err;
62 6f4d00ee 2013-09-23 0intro }
63 6f4d00ee 2013-09-23 0intro blockPut(b);
64 6f4d00ee 2013-09-23 0intro
65 6f4d00ee 2013-09-23 0intro fs->ehi = super.epochHigh;
66 6f4d00ee 2013-09-23 0intro fs->elo = super.epochLow;
67 6f4d00ee 2013-09-23 0intro
68 6f4d00ee 2013-09-23 0intro //fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active);
69 6f4d00ee 2013-09-23 0intro
70 6f4d00ee 2013-09-23 0intro fs->source = sourceRoot(fs, super.active, mode);
71 6f4d00ee 2013-09-23 0intro if(fs->source == nil){
72 6f4d00ee 2013-09-23 0intro /*
73 6f4d00ee 2013-09-23 0intro * Perhaps it failed because the block is copy-on-write.
74 6f4d00ee 2013-09-23 0intro * Do the copy and try again.
75 6f4d00ee 2013-09-23 0intro */
76 4b576658 2013-09-23 0intro rerrstr(e, sizeof e);
77 4b576658 2013-09-23 0intro if(mode == OReadOnly || strcmp(e, EBadRoot) != 0)
78 6f4d00ee 2013-09-23 0intro goto Err;
79 6f4d00ee 2013-09-23 0intro b = cacheLocalData(fs->cache, super.active, BtDir, RootTag,
80 6f4d00ee 2013-09-23 0intro OReadWrite, 0);
81 6f4d00ee 2013-09-23 0intro if(b == nil){
82 4b576658 2013-09-23 0intro werrstr("cacheLocalData: %r");
83 6f4d00ee 2013-09-23 0intro goto Err;
84 6f4d00ee 2013-09-23 0intro }
85 6f4d00ee 2013-09-23 0intro if(b->l.epoch == fs->ehi){
86 6f4d00ee 2013-09-23 0intro blockPut(b);
87 4b576658 2013-09-23 0intro werrstr("bad root source block");
88 6f4d00ee 2013-09-23 0intro goto Err;
89 6f4d00ee 2013-09-23 0intro }
90 6f4d00ee 2013-09-23 0intro b = blockCopy(b, RootTag, fs->ehi, fs->elo);
91 6f4d00ee 2013-09-23 0intro if(b == nil)
92 6f4d00ee 2013-09-23 0intro goto Err;
93 6f4d00ee 2013-09-23 0intro localToGlobal(super.active, oscore);
94 6f4d00ee 2013-09-23 0intro super.active = b->addr;
95 6f4d00ee 2013-09-23 0intro bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite);
96 6f4d00ee 2013-09-23 0intro if(bs == nil){
97 6f4d00ee 2013-09-23 0intro blockPut(b);
98 4b576658 2013-09-23 0intro werrstr("cacheLocal: %r");
99 6f4d00ee 2013-09-23 0intro goto Err;
100 6f4d00ee 2013-09-23 0intro }
101 6f4d00ee 2013-09-23 0intro superPack(&super, bs->data);
102 6f4d00ee 2013-09-23 0intro blockDependency(bs, b, 0, oscore, nil);
103 6f4d00ee 2013-09-23 0intro blockPut(b);
104 6f4d00ee 2013-09-23 0intro blockDirty(bs);
105 6f4d00ee 2013-09-23 0intro blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
106 6f4d00ee 2013-09-23 0intro blockPut(bs);
107 6f4d00ee 2013-09-23 0intro fs->source = sourceRoot(fs, super.active, mode);
108 6f4d00ee 2013-09-23 0intro if(fs->source == nil){
109 4b576658 2013-09-23 0intro werrstr("sourceRoot: %r");
110 6f4d00ee 2013-09-23 0intro goto Err;
111 6f4d00ee 2013-09-23 0intro }
112 6f4d00ee 2013-09-23 0intro }
113 6f4d00ee 2013-09-23 0intro
114 6f4d00ee 2013-09-23 0intro //fprint(2, "%s: got fs source\n", argv0);
115 6f4d00ee 2013-09-23 0intro
116 4b576658 2013-09-23 0intro rlock(&fs->elk);
117 6f4d00ee 2013-09-23 0intro fs->file = fileRoot(fs->source);
118 6f4d00ee 2013-09-23 0intro fs->source->file = fs->file; /* point back */
119 4b576658 2013-09-23 0intro runlock(&fs->elk);
120 6f4d00ee 2013-09-23 0intro if(fs->file == nil){
121 4b576658 2013-09-23 0intro werrstr("fileRoot: %r");
122 6f4d00ee 2013-09-23 0intro goto Err;
123 6f4d00ee 2013-09-23 0intro }
124 6f4d00ee 2013-09-23 0intro
125 6f4d00ee 2013-09-23 0intro //fprint(2, "%s: got file root\n", argv0);
126 6f4d00ee 2013-09-23 0intro
127 6f4d00ee 2013-09-23 0intro if(mode == OReadWrite){
128 6f4d00ee 2013-09-23 0intro fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000);
129 6f4d00ee 2013-09-23 0intro fs->snap = snapInit(fs);
130 6f4d00ee 2013-09-23 0intro }
131 6f4d00ee 2013-09-23 0intro return fs;
132 6f4d00ee 2013-09-23 0intro
133 6f4d00ee 2013-09-23 0intro Err:
134 6f4d00ee 2013-09-23 0intro fprint(2, "%s: fsOpen error\n", argv0);
135 6f4d00ee 2013-09-23 0intro fsClose(fs);
136 6f4d00ee 2013-09-23 0intro return nil;
137 6f4d00ee 2013-09-23 0intro }
138 6f4d00ee 2013-09-23 0intro
139 6f4d00ee 2013-09-23 0intro void
140 6f4d00ee 2013-09-23 0intro fsClose(Fs *fs)
141 6f4d00ee 2013-09-23 0intro {
142 4b576658 2013-09-23 0intro rlock(&fs->elk);
143 6f4d00ee 2013-09-23 0intro periodicKill(fs->metaFlush);
144 6f4d00ee 2013-09-23 0intro snapClose(fs->snap);
145 6f4d00ee 2013-09-23 0intro if(fs->file){
146 6f4d00ee 2013-09-23 0intro fileMetaFlush(fs->file, 0);
147 6f4d00ee 2013-09-23 0intro if(!fileDecRef(fs->file))
148 4b576658 2013-09-23 0intro sysfatal("fsClose: files still in use: %r");
149 6f4d00ee 2013-09-23 0intro }
150 6f4d00ee 2013-09-23 0intro fs->file = nil;
151 6f4d00ee 2013-09-23 0intro sourceClose(fs->source);
152 6f4d00ee 2013-09-23 0intro cacheFree(fs->cache);
153 6f4d00ee 2013-09-23 0intro if(fs->arch)
154 6f4d00ee 2013-09-23 0intro archFree(fs->arch);
155 4b576658 2013-09-23 0intro vtfree(fs->name);
156 4b576658 2013-09-23 0intro runlock(&fs->elk);
157 6f4d00ee 2013-09-23 0intro memset(fs, ~0, sizeof(Fs));
158 4b576658 2013-09-23 0intro vtfree(fs);
159 6f4d00ee 2013-09-23 0intro }
160 6f4d00ee 2013-09-23 0intro
161 6f4d00ee 2013-09-23 0intro int
162 6f4d00ee 2013-09-23 0intro fsRedial(Fs *fs, char *host)
163 6f4d00ee 2013-09-23 0intro {
164 4b576658 2013-09-23 0intro if(vtredial(fs->z, host) < 0)
165 6f4d00ee 2013-09-23 0intro return 0;
166 4b576658 2013-09-23 0intro if(vtconnect(fs->z) < 0)
167 6f4d00ee 2013-09-23 0intro return 0;
168 6f4d00ee 2013-09-23 0intro return 1;
169 6f4d00ee 2013-09-23 0intro }
170 6f4d00ee 2013-09-23 0intro
171 6f4d00ee 2013-09-23 0intro File *
172 6f4d00ee 2013-09-23 0intro fsGetRoot(Fs *fs)
173 6f4d00ee 2013-09-23 0intro {
174 6f4d00ee 2013-09-23 0intro return fileIncRef(fs->file);
175 6f4d00ee 2013-09-23 0intro }
176 6f4d00ee 2013-09-23 0intro
177 6f4d00ee 2013-09-23 0intro int
178 6f4d00ee 2013-09-23 0intro fsGetBlockSize(Fs *fs)
179 6f4d00ee 2013-09-23 0intro {
180 6f4d00ee 2013-09-23 0intro return fs->blockSize;
181 6f4d00ee 2013-09-23 0intro }
182 6f4d00ee 2013-09-23 0intro
183 6f4d00ee 2013-09-23 0intro Block*
184 6f4d00ee 2013-09-23 0intro superGet(Cache *c, Super* super)
185 6f4d00ee 2013-09-23 0intro {
186 6f4d00ee 2013-09-23 0intro Block *b;
187 6f4d00ee 2013-09-23 0intro
188 6f4d00ee 2013-09-23 0intro if((b = cacheLocal(c, PartSuper, 0, OReadWrite)) == nil){
189 4b576658 2013-09-23 0intro fprint(2, "%s: superGet: cacheLocal failed: %r\n", argv0);
190 6f4d00ee 2013-09-23 0intro return nil;
191 6f4d00ee 2013-09-23 0intro }
192 6f4d00ee 2013-09-23 0intro if(!superUnpack(super, b->data)){
193 4b576658 2013-09-23 0intro fprint(2, "%s: superGet: superUnpack failed: %r\n", argv0);
194 6f4d00ee 2013-09-23 0intro blockPut(b);
195 6f4d00ee 2013-09-23 0intro return nil;
196 6f4d00ee 2013-09-23 0intro }
197 6f4d00ee 2013-09-23 0intro
198 6f4d00ee 2013-09-23 0intro return b;
199 6f4d00ee 2013-09-23 0intro }
200 6f4d00ee 2013-09-23 0intro
201 6f4d00ee 2013-09-23 0intro void
202 6f4d00ee 2013-09-23 0intro superWrite(Block* b, Super* super, int forceWrite)
203 6f4d00ee 2013-09-23 0intro {
204 6f4d00ee 2013-09-23 0intro superPack(super, b->data);
205 6f4d00ee 2013-09-23 0intro blockDirty(b);
206 6f4d00ee 2013-09-23 0intro if(forceWrite){
207 6f4d00ee 2013-09-23 0intro while(!blockWrite(b, Waitlock)){
208 6f4d00ee 2013-09-23 0intro /* this should no longer happen */
209 6f4d00ee 2013-09-23 0intro fprint(2, "%s: could not write super block; "
210 6f4d00ee 2013-09-23 0intro "waiting 10 seconds\n", argv0);
211 6f4d00ee 2013-09-23 0intro sleep(10*1000);
212 6f4d00ee 2013-09-23 0intro }
213 6f4d00ee 2013-09-23 0intro while(b->iostate != BioClean && b->iostate != BioDirty){
214 6f4d00ee 2013-09-23 0intro assert(b->iostate == BioWriting);
215 4b576658 2013-09-23 0intro rsleep(&b->ioready);
216 6f4d00ee 2013-09-23 0intro }
217 6f4d00ee 2013-09-23 0intro /*
218 6f4d00ee 2013-09-23 0intro * it's okay that b might still be dirty.
219 6f4d00ee 2013-09-23 0intro * that means it got written out but with an old root pointer,
220 6f4d00ee 2013-09-23 0intro * but the other fields went out, and those are the ones
221 6f4d00ee 2013-09-23 0intro * we really care about. (specifically, epochHigh; see fsSnapshot).
222 6f4d00ee 2013-09-23 0intro */
223 6f4d00ee 2013-09-23 0intro }
224 6f4d00ee 2013-09-23 0intro }
225 6f4d00ee 2013-09-23 0intro
226 6f4d00ee 2013-09-23 0intro /*
227 6f4d00ee 2013-09-23 0intro * Prepare the directory to store a snapshot.
228 6f4d00ee 2013-09-23 0intro * Temporary snapshots go into /snapshot/yyyy/mmdd/hhmm[.#]
229 6f4d00ee 2013-09-23 0intro * Archival snapshots go into /archive/yyyy/mmdd[.#].
230 6f4d00ee 2013-09-23 0intro *
231 6f4d00ee 2013-09-23 0intro * TODO This should be rewritten to eliminate most of the duplication.
232 6f4d00ee 2013-09-23 0intro */
233 6f4d00ee 2013-09-23 0intro static File*
234 6f4d00ee 2013-09-23 0intro fileOpenSnapshot(Fs *fs, char *dstpath, int doarchive)
235 6f4d00ee 2013-09-23 0intro {
236 6f4d00ee 2013-09-23 0intro int n;
237 6f4d00ee 2013-09-23 0intro char buf[30], *s, *p, *elem;
238 6f4d00ee 2013-09-23 0intro File *dir, *f;
239 6f4d00ee 2013-09-23 0intro Tm now;
240 6f4d00ee 2013-09-23 0intro
241 6f4d00ee 2013-09-23 0intro if(dstpath){
242 6f4d00ee 2013-09-23 0intro if((p = strrchr(dstpath, '/')) != nil){
243 6f4d00ee 2013-09-23 0intro *p++ = '\0';
244 6f4d00ee 2013-09-23 0intro elem = p;
245 6f4d00ee 2013-09-23 0intro p = dstpath;
246 6f4d00ee 2013-09-23 0intro if(*p == '\0')
247 6f4d00ee 2013-09-23 0intro p = "/";
248 6f4d00ee 2013-09-23 0intro }else{
249 6f4d00ee 2013-09-23 0intro p = "/";
250 6f4d00ee 2013-09-23 0intro elem = dstpath;
251 6f4d00ee 2013-09-23 0intro }
252 6f4d00ee 2013-09-23 0intro if((dir = fileOpen(fs, p)) == nil)
253 6f4d00ee 2013-09-23 0intro return nil;
254 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, elem, ModeDir|ModeSnapshot|0555, "adm");
255 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
256 6f4d00ee 2013-09-23 0intro return f;
257 6f4d00ee 2013-09-23 0intro }else if(doarchive){
258 6f4d00ee 2013-09-23 0intro /*
259 6f4d00ee 2013-09-23 0intro * a snapshot intended to be archived to venti.
260 6f4d00ee 2013-09-23 0intro */
261 6f4d00ee 2013-09-23 0intro dir = fileOpen(fs, "/archive");
262 6f4d00ee 2013-09-23 0intro if(dir == nil)
263 6f4d00ee 2013-09-23 0intro return nil;
264 6f4d00ee 2013-09-23 0intro now = *localtime(time(0));
265 6f4d00ee 2013-09-23 0intro
266 6f4d00ee 2013-09-23 0intro /* yyyy */
267 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof(buf), "%d", now.year+1900);
268 6f4d00ee 2013-09-23 0intro f = fileWalk(dir, buf);
269 6f4d00ee 2013-09-23 0intro if(f == nil)
270 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, buf, ModeDir|0555, "adm");
271 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
272 6f4d00ee 2013-09-23 0intro if(f == nil)
273 6f4d00ee 2013-09-23 0intro return nil;
274 6f4d00ee 2013-09-23 0intro dir = f;
275 6f4d00ee 2013-09-23 0intro
276 6f4d00ee 2013-09-23 0intro /* mmdd[#] */
277 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof(buf), "%02d%02d", now.mon+1, now.mday);
278 6f4d00ee 2013-09-23 0intro s = buf+strlen(buf);
279 6f4d00ee 2013-09-23 0intro for(n=0;; n++){
280 6f4d00ee 2013-09-23 0intro if(n)
281 6f4d00ee 2013-09-23 0intro seprint(s, buf+sizeof(buf), ".%d", n);
282 6f4d00ee 2013-09-23 0intro f = fileWalk(dir, buf);
283 6f4d00ee 2013-09-23 0intro if(f != nil){
284 6f4d00ee 2013-09-23 0intro fileDecRef(f);
285 6f4d00ee 2013-09-23 0intro continue;
286 6f4d00ee 2013-09-23 0intro }
287 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, buf, ModeDir|ModeSnapshot|0555, "adm");
288 6f4d00ee 2013-09-23 0intro break;
289 6f4d00ee 2013-09-23 0intro }
290 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
291 6f4d00ee 2013-09-23 0intro return f;
292 6f4d00ee 2013-09-23 0intro }else{
293 6f4d00ee 2013-09-23 0intro /*
294 6f4d00ee 2013-09-23 0intro * Just a temporary snapshot
295 6f4d00ee 2013-09-23 0intro * We'll use /snapshot/yyyy/mmdd/hhmm.
296 6f4d00ee 2013-09-23 0intro * There may well be a better naming scheme.
297 6f4d00ee 2013-09-23 0intro * (I'd have used hh:mm but ':' is reserved in Microsoft file systems.)
298 6f4d00ee 2013-09-23 0intro */
299 6f4d00ee 2013-09-23 0intro dir = fileOpen(fs, "/snapshot");
300 6f4d00ee 2013-09-23 0intro if(dir == nil)
301 6f4d00ee 2013-09-23 0intro return nil;
302 6f4d00ee 2013-09-23 0intro
303 6f4d00ee 2013-09-23 0intro now = *localtime(time(0));
304 6f4d00ee 2013-09-23 0intro
305 6f4d00ee 2013-09-23 0intro /* yyyy */
306 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof(buf), "%d", now.year+1900);
307 6f4d00ee 2013-09-23 0intro f = fileWalk(dir, buf);
308 6f4d00ee 2013-09-23 0intro if(f == nil)
309 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, buf, ModeDir|0555, "adm");
310 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
311 6f4d00ee 2013-09-23 0intro if(f == nil)
312 6f4d00ee 2013-09-23 0intro return nil;
313 6f4d00ee 2013-09-23 0intro dir = f;
314 6f4d00ee 2013-09-23 0intro
315 6f4d00ee 2013-09-23 0intro /* mmdd */
316 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof(buf), "%02d%02d", now.mon+1, now.mday);
317 6f4d00ee 2013-09-23 0intro f = fileWalk(dir, buf);
318 6f4d00ee 2013-09-23 0intro if(f == nil)
319 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, buf, ModeDir|0555, "adm");
320 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
321 6f4d00ee 2013-09-23 0intro if(f == nil)
322 6f4d00ee 2013-09-23 0intro return nil;
323 6f4d00ee 2013-09-23 0intro dir = f;
324 6f4d00ee 2013-09-23 0intro
325 6f4d00ee 2013-09-23 0intro /* hhmm[.#] */
326 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof buf, "%02d%02d", now.hour, now.min);
327 6f4d00ee 2013-09-23 0intro s = buf+strlen(buf);
328 6f4d00ee 2013-09-23 0intro for(n=0;; n++){
329 6f4d00ee 2013-09-23 0intro if(n)
330 6f4d00ee 2013-09-23 0intro seprint(s, buf+sizeof(buf), ".%d", n);
331 6f4d00ee 2013-09-23 0intro f = fileWalk(dir, buf);
332 6f4d00ee 2013-09-23 0intro if(f != nil){
333 6f4d00ee 2013-09-23 0intro fileDecRef(f);
334 6f4d00ee 2013-09-23 0intro continue;
335 6f4d00ee 2013-09-23 0intro }
336 6f4d00ee 2013-09-23 0intro f = fileCreate(dir, buf, ModeDir|ModeSnapshot|0555, "adm");
337 6f4d00ee 2013-09-23 0intro break;
338 6f4d00ee 2013-09-23 0intro }
339 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
340 6f4d00ee 2013-09-23 0intro return f;
341 6f4d00ee 2013-09-23 0intro }
342 6f4d00ee 2013-09-23 0intro }
343 6f4d00ee 2013-09-23 0intro
344 6f4d00ee 2013-09-23 0intro static int
345 6f4d00ee 2013-09-23 0intro fsNeedArch(Fs *fs, uint archMinute)
346 6f4d00ee 2013-09-23 0intro {
347 6f4d00ee 2013-09-23 0intro int need;
348 6f4d00ee 2013-09-23 0intro File *f;
349 6f4d00ee 2013-09-23 0intro char buf[100];
350 6f4d00ee 2013-09-23 0intro Tm now;
351 6f4d00ee 2013-09-23 0intro ulong then;
352 6f4d00ee 2013-09-23 0intro
353 6f4d00ee 2013-09-23 0intro then = time(0);
354 6f4d00ee 2013-09-23 0intro now = *localtime(then);
355 6f4d00ee 2013-09-23 0intro
356 6f4d00ee 2013-09-23 0intro /* back up to yesterday if necessary */
357 6f4d00ee 2013-09-23 0intro if(now.hour < archMinute/60
358 6f4d00ee 2013-09-23 0intro || now.hour == archMinute/60 && now.min < archMinute%60)
359 6f4d00ee 2013-09-23 0intro now = *localtime(then-86400);
360 6f4d00ee 2013-09-23 0intro
361 6f4d00ee 2013-09-23 0intro snprint(buf, sizeof buf, "/archive/%d/%02d%02d",
362 6f4d00ee 2013-09-23 0intro now.year+1900, now.mon+1, now.mday);
363 6f4d00ee 2013-09-23 0intro need = 1;
364 4b576658 2013-09-23 0intro rlock(&fs->elk);
365 6f4d00ee 2013-09-23 0intro f = fileOpen(fs, buf);
366 6f4d00ee 2013-09-23 0intro if(f){
367 6f4d00ee 2013-09-23 0intro need = 0;
368 6f4d00ee 2013-09-23 0intro fileDecRef(f);
369 6f4d00ee 2013-09-23 0intro }
370 4b576658 2013-09-23 0intro runlock(&fs->elk);
371 6f4d00ee 2013-09-23 0intro return need;
372 6f4d00ee 2013-09-23 0intro }
373 6f4d00ee 2013-09-23 0intro
374 6f4d00ee 2013-09-23 0intro int
375 6f4d00ee 2013-09-23 0intro fsEpochLow(Fs *fs, u32int low)
376 6f4d00ee 2013-09-23 0intro {
377 6f4d00ee 2013-09-23 0intro Block *bs;
378 6f4d00ee 2013-09-23 0intro Super super;
379 6f4d00ee 2013-09-23 0intro
380 4b576658 2013-09-23 0intro wlock(&fs->elk);
381 6f4d00ee 2013-09-23 0intro if(low > fs->ehi){
382 4b576658 2013-09-23 0intro werrstr("bad low epoch (must be <= %ud)", fs->ehi);
383 4b576658 2013-09-23 0intro wunlock(&fs->elk);
384 6f4d00ee 2013-09-23 0intro return 0;
385 6f4d00ee 2013-09-23 0intro }
386 6f4d00ee 2013-09-23 0intro
387 6f4d00ee 2013-09-23 0intro if((bs = superGet(fs->cache, &super)) == nil){
388 4b576658 2013-09-23 0intro wunlock(&fs->elk);
389 6f4d00ee 2013-09-23 0intro return 0;
390 6f4d00ee 2013-09-23 0intro }
391 6f4d00ee 2013-09-23 0intro
392 6f4d00ee 2013-09-23 0intro super.epochLow = low;
393 6f4d00ee 2013-09-23 0intro fs->elo = low;
394 6f4d00ee 2013-09-23 0intro superWrite(bs, &super, 1);
395 6f4d00ee 2013-09-23 0intro blockPut(bs);
396 4b576658 2013-09-23 0intro wunlock(&fs->elk);
397 6f4d00ee 2013-09-23 0intro
398 6f4d00ee 2013-09-23 0intro return 1;
399 6f4d00ee 2013-09-23 0intro }
400 6f4d00ee 2013-09-23 0intro
401 6f4d00ee 2013-09-23 0intro static int
402 6f4d00ee 2013-09-23 0intro bumpEpoch(Fs *fs, int doarchive)
403 6f4d00ee 2013-09-23 0intro {
404 6f4d00ee 2013-09-23 0intro uchar oscore[VtScoreSize];
405 6f4d00ee 2013-09-23 0intro u32int oldaddr;
406 6f4d00ee 2013-09-23 0intro Block *b, *bs;
407 6f4d00ee 2013-09-23 0intro Entry e;
408 6f4d00ee 2013-09-23 0intro Source *r;
409 6f4d00ee 2013-09-23 0intro Super super;
410 6f4d00ee 2013-09-23 0intro
411 6f4d00ee 2013-09-23 0intro /*
412 6f4d00ee 2013-09-23 0intro * Duplicate the root block.
413 6f4d00ee 2013-09-23 0intro *
414 6f4d00ee 2013-09-23 0intro * As a hint to flchk, the garbage collector,
415 6f4d00ee 2013-09-23 0intro * and any (human) debuggers, store a pointer
416 6f4d00ee 2013-09-23 0intro * to the old root block in entry 1 of the new root block.
417 6f4d00ee 2013-09-23 0intro */
418 6f4d00ee 2013-09-23 0intro r = fs->source;
419 6f4d00ee 2013-09-23 0intro b = cacheGlobal(fs->cache, r->score, BtDir, RootTag, OReadOnly);
420 6f4d00ee 2013-09-23 0intro if(b == nil)
421 6f4d00ee 2013-09-23 0intro return 0;
422 6f4d00ee 2013-09-23 0intro
423 6f4d00ee 2013-09-23 0intro memset(&e, 0, sizeof e);
424 4b576658 2013-09-23 0intro e.flags = VtEntryActive | VtEntryLocal | _VtEntryDir;
425 6f4d00ee 2013-09-23 0intro memmove(e.score, b->score, VtScoreSize);
426 6f4d00ee 2013-09-23 0intro e.tag = RootTag;
427 6f4d00ee 2013-09-23 0intro e.snap = b->l.epoch;
428 6f4d00ee 2013-09-23 0intro
429 6f4d00ee 2013-09-23 0intro b = blockCopy(b, RootTag, fs->ehi+1, fs->elo);
430 6f4d00ee 2013-09-23 0intro if(b == nil){
431 4b576658 2013-09-23 0intro fprint(2, "%s: bumpEpoch: blockCopy: %r\n", argv0);
432 6f4d00ee 2013-09-23 0intro return 0;
433 6f4d00ee 2013-09-23 0intro }
434 6f4d00ee 2013-09-23 0intro
435 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "%s: snapshot root from %d to %d\n", argv0, oldaddr, b->addr);
436 6f4d00ee 2013-09-23 0intro entryPack(&e, b->data, 1);
437 6f4d00ee 2013-09-23 0intro blockDirty(b);
438 6f4d00ee 2013-09-23 0intro
439 6f4d00ee 2013-09-23 0intro /*
440 6f4d00ee 2013-09-23 0intro * Update the superblock with the new root and epoch.
441 6f4d00ee 2013-09-23 0intro */
442 6f4d00ee 2013-09-23 0intro if((bs = superGet(fs->cache, &super)) == nil)
443 6f4d00ee 2013-09-23 0intro return 0;
444 6f4d00ee 2013-09-23 0intro
445 6f4d00ee 2013-09-23 0intro fs->ehi++;
446 6f4d00ee 2013-09-23 0intro memmove(r->score, b->score, VtScoreSize);
447 6f4d00ee 2013-09-23 0intro r->epoch = fs->ehi;
448 6f4d00ee 2013-09-23 0intro
449 6f4d00ee 2013-09-23 0intro super.epochHigh = fs->ehi;
450 6f4d00ee 2013-09-23 0intro oldaddr = super.active;
451 6f4d00ee 2013-09-23 0intro super.active = b->addr;
452 6f4d00ee 2013-09-23 0intro if(doarchive)
453 6f4d00ee 2013-09-23 0intro super.next = oldaddr;
454 6f4d00ee 2013-09-23 0intro
455 6f4d00ee 2013-09-23 0intro /*
456 6f4d00ee 2013-09-23 0intro * Record that the new super.active can't get written out until
457 6f4d00ee 2013-09-23 0intro * the new b gets written out. Until then, use the old value.
458 6f4d00ee 2013-09-23 0intro */
459 6f4d00ee 2013-09-23 0intro localToGlobal(oldaddr, oscore);
460 6f4d00ee 2013-09-23 0intro blockDependency(bs, b, 0, oscore, nil);
461 6f4d00ee 2013-09-23 0intro blockPut(b);
462 6f4d00ee 2013-09-23 0intro
463 6f4d00ee 2013-09-23 0intro /*
464 6f4d00ee 2013-09-23 0intro * We force the super block to disk so that super.epochHigh gets updated.
465 6f4d00ee 2013-09-23 0intro * Otherwise, if we crash and come back, we might incorrectly treat as active
466 6f4d00ee 2013-09-23 0intro * some of the blocks that making up the snapshot we just created.
467 6f4d00ee 2013-09-23 0intro * Basically every block in the active file system and all the blocks in
468 6f4d00ee 2013-09-23 0intro * the recently-created snapshot depend on the super block now.
469 6f4d00ee 2013-09-23 0intro * Rather than record all those dependencies, we just force the block to disk.
470 6f4d00ee 2013-09-23 0intro *
471 6f4d00ee 2013-09-23 0intro * Note that blockWrite might actually (will probably) send a slightly outdated
472 6f4d00ee 2013-09-23 0intro * super.active to disk. It will be the address of the most recent root that has
473 6f4d00ee 2013-09-23 0intro * gone to disk.
474 6f4d00ee 2013-09-23 0intro */
475 6f4d00ee 2013-09-23 0intro superWrite(bs, &super, 1);
476 6f4d00ee 2013-09-23 0intro blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
477 6f4d00ee 2013-09-23 0intro blockPut(bs);
478 6f4d00ee 2013-09-23 0intro
479 6f4d00ee 2013-09-23 0intro return 1;
480 6f4d00ee 2013-09-23 0intro }
481 6f4d00ee 2013-09-23 0intro
482 6f4d00ee 2013-09-23 0intro int
483 6f4d00ee 2013-09-23 0intro saveQid(Fs *fs)
484 6f4d00ee 2013-09-23 0intro {
485 6f4d00ee 2013-09-23 0intro Block *b;
486 6f4d00ee 2013-09-23 0intro Super super;
487 6f4d00ee 2013-09-23 0intro u64int qidMax;
488 6f4d00ee 2013-09-23 0intro
489 6f4d00ee 2013-09-23 0intro if((b = superGet(fs->cache, &super)) == nil)
490 6f4d00ee 2013-09-23 0intro return 0;
491 6f4d00ee 2013-09-23 0intro qidMax = super.qid;
492 6f4d00ee 2013-09-23 0intro blockPut(b);
493 6f4d00ee 2013-09-23 0intro
494 6f4d00ee 2013-09-23 0intro if(!fileSetQidSpace(fs->file, 0, qidMax))
495 6f4d00ee 2013-09-23 0intro return 0;
496 6f4d00ee 2013-09-23 0intro
497 6f4d00ee 2013-09-23 0intro return 1;
498 6f4d00ee 2013-09-23 0intro }
499 6f4d00ee 2013-09-23 0intro
500 6f4d00ee 2013-09-23 0intro int
501 6f4d00ee 2013-09-23 0intro fsSnapshot(Fs *fs, char *srcpath, char *dstpath, int doarchive)
502 6f4d00ee 2013-09-23 0intro {
503 6f4d00ee 2013-09-23 0intro File *src, *dst;
504 6f4d00ee 2013-09-23 0intro
505 6f4d00ee 2013-09-23 0intro assert(fs->mode == OReadWrite);
506 6f4d00ee 2013-09-23 0intro
507 6f4d00ee 2013-09-23 0intro dst = nil;
508 6f4d00ee 2013-09-23 0intro
509 6f4d00ee 2013-09-23 0intro if(fs->halted){
510 4b576658 2013-09-23 0intro werrstr("file system is halted");
511 6f4d00ee 2013-09-23 0intro return 0;
512 6f4d00ee 2013-09-23 0intro }
513 6f4d00ee 2013-09-23 0intro
514 6f4d00ee 2013-09-23 0intro /*
515 6f4d00ee 2013-09-23 0intro * Freeze file system activity.
516 6f4d00ee 2013-09-23 0intro */
517 4b576658 2013-09-23 0intro wlock(&fs->elk);
518 6f4d00ee 2013-09-23 0intro
519 6f4d00ee 2013-09-23 0intro /*
520 6f4d00ee 2013-09-23 0intro * Get the root of the directory we're going to save.
521 6f4d00ee 2013-09-23 0intro */
522 6f4d00ee 2013-09-23 0intro if(srcpath == nil)
523 6f4d00ee 2013-09-23 0intro srcpath = "/active";
524 6f4d00ee 2013-09-23 0intro src = fileOpen(fs, srcpath);
525 6f4d00ee 2013-09-23 0intro if(src == nil)
526 6f4d00ee 2013-09-23 0intro goto Err;
527 6f4d00ee 2013-09-23 0intro
528 6f4d00ee 2013-09-23 0intro /*
529 6f4d00ee 2013-09-23 0intro * It is important that we maintain the invariant that:
530 6f4d00ee 2013-09-23 0intro * if both b and bb are marked as Active with start epoch e
531 6f4d00ee 2013-09-23 0intro * and b points at bb, then no other pointers to bb exist.
532 fa325e9b 2020-01-10 cross *
533 6f4d00ee 2013-09-23 0intro * When bb is unlinked from b, its close epoch is set to b's epoch.
534 6f4d00ee 2013-09-23 0intro * A block with epoch == close epoch is
535 6f4d00ee 2013-09-23 0intro * treated as free by cacheAllocBlock; this aggressively
536 6f4d00ee 2013-09-23 0intro * reclaims blocks after they have been stored to Venti.
537 6f4d00ee 2013-09-23 0intro *
538 6f4d00ee 2013-09-23 0intro * Let's say src->source is block sb, and src->msource is block
539 6f4d00ee 2013-09-23 0intro * mb. Let's also say that block b holds the Entry structures for
540 6f4d00ee 2013-09-23 0intro * both src->source and src->msource (their Entry structures might
541 6f4d00ee 2013-09-23 0intro * be in different blocks, but the argument is the same).
542 6f4d00ee 2013-09-23 0intro * That is, right now we have:
543 6f4d00ee 2013-09-23 0intro *
544 6f4d00ee 2013-09-23 0intro * b Active w/ epoch e, holds ptrs to sb and mb.
545 6f4d00ee 2013-09-23 0intro * sb Active w/ epoch e.
546 6f4d00ee 2013-09-23 0intro * mb Active w/ epoch e.
547 6f4d00ee 2013-09-23 0intro *
548 6f4d00ee 2013-09-23 0intro * With things as they are now, the invariant requires that
549 6f4d00ee 2013-09-23 0intro * b holds the only pointers to sb and mb. We want to record
550 6f4d00ee 2013-09-23 0intro * pointers to sb and mb in new Entries corresponding to dst,
551 6f4d00ee 2013-09-23 0intro * which breaks the invariant. Thus we need to do something
552 6f4d00ee 2013-09-23 0intro * about b. Specifically, we bump the file system's epoch and
553 6f4d00ee 2013-09-23 0intro * then rewalk the path from the root down to and including b.
554 6f4d00ee 2013-09-23 0intro * This will copy-on-write as we walk, so now the state will be:
555 6f4d00ee 2013-09-23 0intro *
556 6f4d00ee 2013-09-23 0intro * b Snap w/ epoch e, holds ptrs to sb and mb.
557 6f4d00ee 2013-09-23 0intro * new-b Active w/ epoch e+1, holds ptrs to sb and mb.
558 6f4d00ee 2013-09-23 0intro * sb Active w/ epoch e.
559 6f4d00ee 2013-09-23 0intro * mb Active w/ epoch e.
560 6f4d00ee 2013-09-23 0intro *
561 6f4d00ee 2013-09-23 0intro * In this state, it's perfectly okay to make more pointers to sb and mb.
562 6f4d00ee 2013-09-23 0intro */
563 6f4d00ee 2013-09-23 0intro if(!bumpEpoch(fs, 0) || !fileWalkSources(src))
564 6f4d00ee 2013-09-23 0intro goto Err;
565 6f4d00ee 2013-09-23 0intro
566 6f4d00ee 2013-09-23 0intro /*
567 6f4d00ee 2013-09-23 0intro * Sync to disk. I'm not sure this is necessary, but better safe than sorry.
568 6f4d00ee 2013-09-23 0intro */
569 6f4d00ee 2013-09-23 0intro cacheFlush(fs->cache, 1);
570 6f4d00ee 2013-09-23 0intro
571 6f4d00ee 2013-09-23 0intro /*
572 6f4d00ee 2013-09-23 0intro * Create the directory where we will store the copy of src.
573 6f4d00ee 2013-09-23 0intro */
574 6f4d00ee 2013-09-23 0intro dst = fileOpenSnapshot(fs, dstpath, doarchive);
575 6f4d00ee 2013-09-23 0intro if(dst == nil)
576 6f4d00ee 2013-09-23 0intro goto Err;
577 6f4d00ee 2013-09-23 0intro
578 6f4d00ee 2013-09-23 0intro /*
579 6f4d00ee 2013-09-23 0intro * Actually make the copy by setting dst's source and msource
580 6f4d00ee 2013-09-23 0intro * to be src's.
581 6f4d00ee 2013-09-23 0intro */
582 6f4d00ee 2013-09-23 0intro if(!fileSnapshot(dst, src, fs->ehi-1, doarchive))
583 6f4d00ee 2013-09-23 0intro goto Err;
584 6f4d00ee 2013-09-23 0intro
585 6f4d00ee 2013-09-23 0intro fileDecRef(src);
586 6f4d00ee 2013-09-23 0intro fileDecRef(dst);
587 6f4d00ee 2013-09-23 0intro src = nil;
588 6f4d00ee 2013-09-23 0intro dst = nil;
589 6f4d00ee 2013-09-23 0intro
590 6f4d00ee 2013-09-23 0intro /*
591 6f4d00ee 2013-09-23 0intro * Make another copy of the file system. This one is for the
592 6f4d00ee 2013-09-23 0intro * archiver, so that the file system we archive has the recently
593 6f4d00ee 2013-09-23 0intro * added snapshot both in /active and in /archive/yyyy/mmdd[.#].
594 6f4d00ee 2013-09-23 0intro */
595 6f4d00ee 2013-09-23 0intro if(doarchive){
596 6f4d00ee 2013-09-23 0intro if(!saveQid(fs))
597 6f4d00ee 2013-09-23 0intro goto Err;
598 6f4d00ee 2013-09-23 0intro if(!bumpEpoch(fs, 1))
599 6f4d00ee 2013-09-23 0intro goto Err;
600 6f4d00ee 2013-09-23 0intro }
601 6f4d00ee 2013-09-23 0intro
602 4b576658 2013-09-23 0intro wunlock(&fs->elk);
603 6f4d00ee 2013-09-23 0intro
604 6f4d00ee 2013-09-23 0intro /* BUG? can fs->arch fall out from under us here? */
605 6f4d00ee 2013-09-23 0intro if(doarchive && fs->arch)
606 6f4d00ee 2013-09-23 0intro archKick(fs->arch);
607 6f4d00ee 2013-09-23 0intro
608 6f4d00ee 2013-09-23 0intro return 1;
609 6f4d00ee 2013-09-23 0intro
610 6f4d00ee 2013-09-23 0intro Err:
611 4b576658 2013-09-23 0intro fprint(2, "%s: fsSnapshot: %r\n", argv0);
612 6f4d00ee 2013-09-23 0intro if(src)
613 6f4d00ee 2013-09-23 0intro fileDecRef(src);
614 6f4d00ee 2013-09-23 0intro if(dst)
615 6f4d00ee 2013-09-23 0intro fileDecRef(dst);
616 4b576658 2013-09-23 0intro wunlock(&fs->elk);
617 6f4d00ee 2013-09-23 0intro return 0;
618 6f4d00ee 2013-09-23 0intro }
619 6f4d00ee 2013-09-23 0intro
620 6f4d00ee 2013-09-23 0intro int
621 6f4d00ee 2013-09-23 0intro fsVac(Fs *fs, char *name, uchar score[VtScoreSize])
622 6f4d00ee 2013-09-23 0intro {
623 6f4d00ee 2013-09-23 0intro int r;
624 6f4d00ee 2013-09-23 0intro DirEntry de;
625 6f4d00ee 2013-09-23 0intro Entry e, ee;
626 6f4d00ee 2013-09-23 0intro File *f;
627 6f4d00ee 2013-09-23 0intro
628 4b576658 2013-09-23 0intro rlock(&fs->elk);
629 6f4d00ee 2013-09-23 0intro f = fileOpen(fs, name);
630 6f4d00ee 2013-09-23 0intro if(f == nil){
631 4b576658 2013-09-23 0intro runlock(&fs->elk);
632 6f4d00ee 2013-09-23 0intro return 0;
633 6f4d00ee 2013-09-23 0intro }
634 6f4d00ee 2013-09-23 0intro
635 6f4d00ee 2013-09-23 0intro if(!fileGetSources(f, &e, &ee) || !fileGetDir(f, &de)){
636 6f4d00ee 2013-09-23 0intro fileDecRef(f);
637 4b576658 2013-09-23 0intro runlock(&fs->elk);
638 6f4d00ee 2013-09-23 0intro return 0;
639 6f4d00ee 2013-09-23 0intro }
640 6f4d00ee 2013-09-23 0intro fileDecRef(f);
641 6f4d00ee 2013-09-23 0intro
642 6f4d00ee 2013-09-23 0intro r = mkVac(fs->z, fs->blockSize, &e, &ee, &de, score);
643 4b576658 2013-09-23 0intro runlock(&fs->elk);
644 6f4d00ee 2013-09-23 0intro return r;
645 6f4d00ee 2013-09-23 0intro }
646 6f4d00ee 2013-09-23 0intro
647 6f4d00ee 2013-09-23 0intro static int
648 4b576658 2013-09-23 0intro vtWriteBlock(VtConn *z, uchar *buf, uint n, uint type, uchar score[VtScoreSize])
649 6f4d00ee 2013-09-23 0intro {
650 4b576658 2013-09-23 0intro if(vtwrite(z, score, type, buf, n) < 0)
651 6f4d00ee 2013-09-23 0intro return 0;
652 4b576658 2013-09-23 0intro if(vtsha1check(score, buf, n) < 0)
653 6f4d00ee 2013-09-23 0intro return 0;
654 6f4d00ee 2013-09-23 0intro return 1;
655 6f4d00ee 2013-09-23 0intro }
656 6f4d00ee 2013-09-23 0intro
657 6f4d00ee 2013-09-23 0intro int
658 4b576658 2013-09-23 0intro mkVac(VtConn *z, uint blockSize, Entry *pe, Entry *pee, DirEntry *pde, uchar score[VtScoreSize])
659 6f4d00ee 2013-09-23 0intro {
660 6f4d00ee 2013-09-23 0intro uchar buf[8192];
661 6f4d00ee 2013-09-23 0intro int i;
662 6f4d00ee 2013-09-23 0intro uchar *p;
663 6f4d00ee 2013-09-23 0intro uint n;
664 6f4d00ee 2013-09-23 0intro DirEntry de;
665 6f4d00ee 2013-09-23 0intro Entry e, ee, eee;
666 6f4d00ee 2013-09-23 0intro MetaBlock mb;
667 6f4d00ee 2013-09-23 0intro MetaEntry me;
668 6f4d00ee 2013-09-23 0intro VtRoot root;
669 6f4d00ee 2013-09-23 0intro
670 6f4d00ee 2013-09-23 0intro e = *pe;
671 6f4d00ee 2013-09-23 0intro ee = *pee;
672 6f4d00ee 2013-09-23 0intro de = *pde;
673 6f4d00ee 2013-09-23 0intro
674 6f4d00ee 2013-09-23 0intro if(globalToLocal(e.score) != NilBlock
675 6f4d00ee 2013-09-23 0intro || (ee.flags&VtEntryActive && globalToLocal(ee.score) != NilBlock)){
676 4b576658 2013-09-23 0intro werrstr("can only vac paths already stored on venti");
677 6f4d00ee 2013-09-23 0intro return 0;
678 6f4d00ee 2013-09-23 0intro }
679 6f4d00ee 2013-09-23 0intro
680 6f4d00ee 2013-09-23 0intro /*
681 6f4d00ee 2013-09-23 0intro * Build metadata source for root.
682 6f4d00ee 2013-09-23 0intro */
683 6f4d00ee 2013-09-23 0intro n = deSize(&de);
684 6f4d00ee 2013-09-23 0intro if(n+MetaHeaderSize+MetaIndexSize > sizeof buf){
685 4b576658 2013-09-23 0intro werrstr("DirEntry too big");
686 6f4d00ee 2013-09-23 0intro return 0;
687 6f4d00ee 2013-09-23 0intro }
688 6f4d00ee 2013-09-23 0intro memset(buf, 0, sizeof buf);
689 6f4d00ee 2013-09-23 0intro mbInit(&mb, buf, n+MetaHeaderSize+MetaIndexSize, 1);
690 6f4d00ee 2013-09-23 0intro p = mbAlloc(&mb, n);
691 6f4d00ee 2013-09-23 0intro if(p == nil)
692 6f4d00ee 2013-09-23 0intro abort();
693 6f4d00ee 2013-09-23 0intro mbSearch(&mb, de.elem, &i, &me);
694 6f4d00ee 2013-09-23 0intro assert(me.p == nil);
695 6f4d00ee 2013-09-23 0intro me.p = p;
696 6f4d00ee 2013-09-23 0intro me.size = n;
697 6f4d00ee 2013-09-23 0intro dePack(&de, &me);
698 6f4d00ee 2013-09-23 0intro mbInsert(&mb, i, &me);
699 6f4d00ee 2013-09-23 0intro mbPack(&mb);
700 6f4d00ee 2013-09-23 0intro
701 6f4d00ee 2013-09-23 0intro eee.size = n+MetaHeaderSize+MetaIndexSize;
702 6f4d00ee 2013-09-23 0intro if(!vtWriteBlock(z, buf, eee.size, VtDataType, eee.score))
703 6f4d00ee 2013-09-23 0intro return 0;
704 6f4d00ee 2013-09-23 0intro eee.psize = 8192;
705 6f4d00ee 2013-09-23 0intro eee.dsize = 8192;
706 6f4d00ee 2013-09-23 0intro eee.depth = 0;
707 6f4d00ee 2013-09-23 0intro eee.flags = VtEntryActive;
708 6f4d00ee 2013-09-23 0intro
709 6f4d00ee 2013-09-23 0intro /*
710 6f4d00ee 2013-09-23 0intro * Build root source with three entries in it.
711 6f4d00ee 2013-09-23 0intro */
712 6f4d00ee 2013-09-23 0intro entryPack(&e, buf, 0);
713 6f4d00ee 2013-09-23 0intro entryPack(&ee, buf, 1);
714 6f4d00ee 2013-09-23 0intro entryPack(&eee, buf, 2);
715 6f4d00ee 2013-09-23 0intro
716 6f4d00ee 2013-09-23 0intro n = VtEntrySize*3;
717 6f4d00ee 2013-09-23 0intro memset(&root, 0, sizeof root);
718 6f4d00ee 2013-09-23 0intro if(!vtWriteBlock(z, buf, n, VtDirType, root.score))
719 6f4d00ee 2013-09-23 0intro return 0;
720 6f4d00ee 2013-09-23 0intro
721 6f4d00ee 2013-09-23 0intro /*
722 6f4d00ee 2013-09-23 0intro * Save root.
723 6f4d00ee 2013-09-23 0intro */
724 6f4d00ee 2013-09-23 0intro strecpy(root.type, root.type+sizeof root.type, "vac");
725 6f4d00ee 2013-09-23 0intro strecpy(root.name, root.name+sizeof root.name, de.elem);
726 4b576658 2013-09-23 0intro root.blocksize = blockSize;
727 4b576658 2013-09-23 0intro vtrootpack(&root, buf);
728 6f4d00ee 2013-09-23 0intro if(!vtWriteBlock(z, buf, VtRootSize, VtRootType, score))
729 6f4d00ee 2013-09-23 0intro return 0;
730 6f4d00ee 2013-09-23 0intro
731 6f4d00ee 2013-09-23 0intro return 1;
732 6f4d00ee 2013-09-23 0intro }
733 6f4d00ee 2013-09-23 0intro
734 6f4d00ee 2013-09-23 0intro int
735 6f4d00ee 2013-09-23 0intro fsSync(Fs *fs)
736 6f4d00ee 2013-09-23 0intro {
737 4b576658 2013-09-23 0intro wlock(&fs->elk);
738 6f4d00ee 2013-09-23 0intro fileMetaFlush(fs->file, 1);
739 6f4d00ee 2013-09-23 0intro cacheFlush(fs->cache, 1);
740 4b576658 2013-09-23 0intro wunlock(&fs->elk);
741 6f4d00ee 2013-09-23 0intro return 1;
742 6f4d00ee 2013-09-23 0intro }
743 6f4d00ee 2013-09-23 0intro
744 6f4d00ee 2013-09-23 0intro int
745 6f4d00ee 2013-09-23 0intro fsHalt(Fs *fs)
746 6f4d00ee 2013-09-23 0intro {
747 4b576658 2013-09-23 0intro wlock(&fs->elk);
748 6f4d00ee 2013-09-23 0intro fs->halted = 1;
749 6f4d00ee 2013-09-23 0intro fileMetaFlush(fs->file, 1);
750 6f4d00ee 2013-09-23 0intro cacheFlush(fs->cache, 1);
751 6f4d00ee 2013-09-23 0intro return 1;
752 6f4d00ee 2013-09-23 0intro }
753 6f4d00ee 2013-09-23 0intro
754 6f4d00ee 2013-09-23 0intro int
755 6f4d00ee 2013-09-23 0intro fsUnhalt(Fs *fs)
756 6f4d00ee 2013-09-23 0intro {
757 6f4d00ee 2013-09-23 0intro if(!fs->halted)
758 6f4d00ee 2013-09-23 0intro return 0;
759 6f4d00ee 2013-09-23 0intro fs->halted = 0;
760 4b576658 2013-09-23 0intro wunlock(&fs->elk);
761 6f4d00ee 2013-09-23 0intro return 1;
762 6f4d00ee 2013-09-23 0intro }
763 6f4d00ee 2013-09-23 0intro
764 6f4d00ee 2013-09-23 0intro int
765 6f4d00ee 2013-09-23 0intro fsNextQid(Fs *fs, u64int *qid)
766 6f4d00ee 2013-09-23 0intro {
767 6f4d00ee 2013-09-23 0intro Block *b;
768 6f4d00ee 2013-09-23 0intro Super super;
769 6f4d00ee 2013-09-23 0intro
770 6f4d00ee 2013-09-23 0intro if((b = superGet(fs->cache, &super)) == nil)
771 6f4d00ee 2013-09-23 0intro return 0;
772 6f4d00ee 2013-09-23 0intro
773 6f4d00ee 2013-09-23 0intro *qid = super.qid++;
774 6f4d00ee 2013-09-23 0intro
775 6f4d00ee 2013-09-23 0intro /*
776 6f4d00ee 2013-09-23 0intro * It's okay if the super block doesn't go to disk immediately,
777 6f4d00ee 2013-09-23 0intro * since fileMetaAlloc will record a dependency between the
778 6f4d00ee 2013-09-23 0intro * block holding this qid and the super block. See file.c:/^fileMetaAlloc.
779 6f4d00ee 2013-09-23 0intro */
780 6f4d00ee 2013-09-23 0intro superWrite(b, &super, 0);
781 6f4d00ee 2013-09-23 0intro blockPut(b);
782 6f4d00ee 2013-09-23 0intro return 1;
783 6f4d00ee 2013-09-23 0intro }
784 6f4d00ee 2013-09-23 0intro
785 6f4d00ee 2013-09-23 0intro static void
786 6f4d00ee 2013-09-23 0intro fsMetaFlush(void *a)
787 6f4d00ee 2013-09-23 0intro {
788 6f4d00ee 2013-09-23 0intro int rv;
789 6f4d00ee 2013-09-23 0intro Fs *fs = a;
790 6f4d00ee 2013-09-23 0intro
791 4b576658 2013-09-23 0intro rlock(&fs->elk);
792 6f4d00ee 2013-09-23 0intro rv = fileMetaFlush(fs->file, 1);
793 4b576658 2013-09-23 0intro runlock(&fs->elk);
794 6f4d00ee 2013-09-23 0intro if(rv > 0)
795 6f4d00ee 2013-09-23 0intro cacheFlush(fs->cache, 0);
796 6f4d00ee 2013-09-23 0intro }
797 6f4d00ee 2013-09-23 0intro
798 6f4d00ee 2013-09-23 0intro static int
799 6f4d00ee 2013-09-23 0intro fsEsearch1(File *f, char *path, u32int savetime, u32int *plo)
800 6f4d00ee 2013-09-23 0intro {
801 6f4d00ee 2013-09-23 0intro int n, r;
802 6f4d00ee 2013-09-23 0intro DirEntry de;
803 6f4d00ee 2013-09-23 0intro DirEntryEnum *dee;
804 6f4d00ee 2013-09-23 0intro File *ff;
805 6f4d00ee 2013-09-23 0intro Entry e, ee;
806 6f4d00ee 2013-09-23 0intro char *t;
807 6f4d00ee 2013-09-23 0intro
808 6f4d00ee 2013-09-23 0intro dee = deeOpen(f);
809 6f4d00ee 2013-09-23 0intro if(dee == nil)
810 6f4d00ee 2013-09-23 0intro return 0;
811 6f4d00ee 2013-09-23 0intro
812 6f4d00ee 2013-09-23 0intro n = 0;
813 6f4d00ee 2013-09-23 0intro for(;;){
814 6f4d00ee 2013-09-23 0intro r = deeRead(dee, &de);
815 6f4d00ee 2013-09-23 0intro if(r <= 0)
816 6f4d00ee 2013-09-23 0intro break;
817 6f4d00ee 2013-09-23 0intro if(de.mode & ModeSnapshot){
818 6f4d00ee 2013-09-23 0intro if((ff = fileWalk(f, de.elem)) != nil){
819 6f4d00ee 2013-09-23 0intro if(fileGetSources(ff, &e, &ee))
820 6f4d00ee 2013-09-23 0intro if(de.mtime >= savetime && e.snap != 0)
821 6f4d00ee 2013-09-23 0intro if(e.snap < *plo)
822 6f4d00ee 2013-09-23 0intro *plo = e.snap;
823 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
824 6f4d00ee 2013-09-23 0intro }
825 6f4d00ee 2013-09-23 0intro }
826 6f4d00ee 2013-09-23 0intro else if(de.mode & ModeDir){
827 6f4d00ee 2013-09-23 0intro if((ff = fileWalk(f, de.elem)) != nil){
828 6f4d00ee 2013-09-23 0intro t = smprint("%s/%s", path, de.elem);
829 6f4d00ee 2013-09-23 0intro n += fsEsearch1(ff, t, savetime, plo);
830 4b576658 2013-09-23 0intro vtfree(t);
831 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
832 6f4d00ee 2013-09-23 0intro }
833 6f4d00ee 2013-09-23 0intro }
834 6f4d00ee 2013-09-23 0intro deCleanup(&de);
835 6f4d00ee 2013-09-23 0intro if(r < 0)
836 6f4d00ee 2013-09-23 0intro break;
837 6f4d00ee 2013-09-23 0intro }
838 6f4d00ee 2013-09-23 0intro deeClose(dee);
839 6f4d00ee 2013-09-23 0intro
840 6f4d00ee 2013-09-23 0intro return n;
841 6f4d00ee 2013-09-23 0intro }
842 6f4d00ee 2013-09-23 0intro
843 6f4d00ee 2013-09-23 0intro static int
844 6f4d00ee 2013-09-23 0intro fsEsearch(Fs *fs, char *path, u32int savetime, u32int *plo)
845 6f4d00ee 2013-09-23 0intro {
846 6f4d00ee 2013-09-23 0intro int n;
847 6f4d00ee 2013-09-23 0intro File *f;
848 6f4d00ee 2013-09-23 0intro DirEntry de;
849 6f4d00ee 2013-09-23 0intro
850 6f4d00ee 2013-09-23 0intro f = fileOpen(fs, path);
851 6f4d00ee 2013-09-23 0intro if(f == nil)
852 6f4d00ee 2013-09-23 0intro return 0;
853 6f4d00ee 2013-09-23 0intro if(!fileGetDir(f, &de)){
854 6f4d00ee 2013-09-23 0intro fileDecRef(f);
855 6f4d00ee 2013-09-23 0intro return 0;
856 6f4d00ee 2013-09-23 0intro }
857 6f4d00ee 2013-09-23 0intro if((de.mode & ModeDir) == 0){
858 6f4d00ee 2013-09-23 0intro fileDecRef(f);
859 6f4d00ee 2013-09-23 0intro deCleanup(&de);
860 6f4d00ee 2013-09-23 0intro return 0;
861 6f4d00ee 2013-09-23 0intro }
862 6f4d00ee 2013-09-23 0intro deCleanup(&de);
863 6f4d00ee 2013-09-23 0intro n = fsEsearch1(f, path, savetime, plo);
864 6f4d00ee 2013-09-23 0intro fileDecRef(f);
865 6f4d00ee 2013-09-23 0intro return n;
866 6f4d00ee 2013-09-23 0intro }
867 6f4d00ee 2013-09-23 0intro
868 6f4d00ee 2013-09-23 0intro void
869 6f4d00ee 2013-09-23 0intro fsSnapshotCleanup(Fs *fs, u32int age)
870 6f4d00ee 2013-09-23 0intro {
871 6f4d00ee 2013-09-23 0intro u32int lo;
872 6f4d00ee 2013-09-23 0intro
873 6f4d00ee 2013-09-23 0intro /*
874 6f4d00ee 2013-09-23 0intro * Find the best low epoch we can use,
875 6f4d00ee 2013-09-23 0intro * given that we need to save all the unventied archives
876 6f4d00ee 2013-09-23 0intro * and all the snapshots younger than age.
877 6f4d00ee 2013-09-23 0intro */
878 4b576658 2013-09-23 0intro rlock(&fs->elk);
879 6f4d00ee 2013-09-23 0intro lo = fs->ehi;
880 6f4d00ee 2013-09-23 0intro fsEsearch(fs, "/archive", 0, &lo);
881 6f4d00ee 2013-09-23 0intro fsEsearch(fs, "/snapshot", time(0)-age*60, &lo);
882 4b576658 2013-09-23 0intro runlock(&fs->elk);
883 6f4d00ee 2013-09-23 0intro
884 6f4d00ee 2013-09-23 0intro fsEpochLow(fs, lo);
885 6f4d00ee 2013-09-23 0intro fsSnapshotRemove(fs);
886 6f4d00ee 2013-09-23 0intro }
887 6f4d00ee 2013-09-23 0intro
888 6f4d00ee 2013-09-23 0intro /* remove all snapshots that have expired */
889 6f4d00ee 2013-09-23 0intro /* return number of directory entries remaining */
890 6f4d00ee 2013-09-23 0intro static int
891 6f4d00ee 2013-09-23 0intro fsRsearch1(File *f, char *s)
892 6f4d00ee 2013-09-23 0intro {
893 6f4d00ee 2013-09-23 0intro int n, r;
894 6f4d00ee 2013-09-23 0intro DirEntry de;
895 6f4d00ee 2013-09-23 0intro DirEntryEnum *dee;
896 6f4d00ee 2013-09-23 0intro File *ff;
897 4b576658 2013-09-23 0intro char *t, e[ERRMAX];
898 6f4d00ee 2013-09-23 0intro
899 6f4d00ee 2013-09-23 0intro dee = deeOpen(f);
900 6f4d00ee 2013-09-23 0intro if(dee == nil)
901 6f4d00ee 2013-09-23 0intro return 0;
902 6f4d00ee 2013-09-23 0intro
903 6f4d00ee 2013-09-23 0intro n = 0;
904 6f4d00ee 2013-09-23 0intro for(;;){
905 6f4d00ee 2013-09-23 0intro r = deeRead(dee, &de);
906 6f4d00ee 2013-09-23 0intro if(r <= 0)
907 6f4d00ee 2013-09-23 0intro break;
908 6f4d00ee 2013-09-23 0intro n++;
909 6f4d00ee 2013-09-23 0intro if(de.mode & ModeSnapshot){
910 4b576658 2013-09-23 0intro rerrstr(e, sizeof e);
911 6f4d00ee 2013-09-23 0intro if((ff = fileWalk(f, de.elem)) != nil)
912 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
913 4b576658 2013-09-23 0intro else if(strcmp(e, ESnapOld) == 0){
914 6f4d00ee 2013-09-23 0intro if(fileClri(f, de.elem, "adm"))
915 6f4d00ee 2013-09-23 0intro n--;
916 6f4d00ee 2013-09-23 0intro }
917 6f4d00ee 2013-09-23 0intro }
918 6f4d00ee 2013-09-23 0intro else if(de.mode & ModeDir){
919 6f4d00ee 2013-09-23 0intro if((ff = fileWalk(f, de.elem)) != nil){
920 6f4d00ee 2013-09-23 0intro t = smprint("%s/%s", s, de.elem);
921 6f4d00ee 2013-09-23 0intro if(fsRsearch1(ff, t) == 0)
922 6f4d00ee 2013-09-23 0intro if(fileRemove(ff, "adm"))
923 6f4d00ee 2013-09-23 0intro n--;
924 4b576658 2013-09-23 0intro vtfree(t);
925 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
926 6f4d00ee 2013-09-23 0intro }
927 6f4d00ee 2013-09-23 0intro }
928 6f4d00ee 2013-09-23 0intro deCleanup(&de);
929 6f4d00ee 2013-09-23 0intro if(r < 0)
930 6f4d00ee 2013-09-23 0intro break;
931 6f4d00ee 2013-09-23 0intro }
932 6f4d00ee 2013-09-23 0intro deeClose(dee);
933 6f4d00ee 2013-09-23 0intro
934 6f4d00ee 2013-09-23 0intro return n;
935 6f4d00ee 2013-09-23 0intro }
936 6f4d00ee 2013-09-23 0intro
937 6f4d00ee 2013-09-23 0intro static int
938 6f4d00ee 2013-09-23 0intro fsRsearch(Fs *fs, char *path)
939 6f4d00ee 2013-09-23 0intro {
940 6f4d00ee 2013-09-23 0intro File *f;
941 6f4d00ee 2013-09-23 0intro DirEntry de;
942 6f4d00ee 2013-09-23 0intro
943 6f4d00ee 2013-09-23 0intro f = fileOpen(fs, path);
944 6f4d00ee 2013-09-23 0intro if(f == nil)
945 6f4d00ee 2013-09-23 0intro return 0;
946 6f4d00ee 2013-09-23 0intro if(!fileGetDir(f, &de)){
947 6f4d00ee 2013-09-23 0intro fileDecRef(f);
948 6f4d00ee 2013-09-23 0intro return 0;
949 6f4d00ee 2013-09-23 0intro }
950 6f4d00ee 2013-09-23 0intro if((de.mode & ModeDir) == 0){
951 6f4d00ee 2013-09-23 0intro fileDecRef(f);
952 6f4d00ee 2013-09-23 0intro deCleanup(&de);
953 6f4d00ee 2013-09-23 0intro return 0;
954 6f4d00ee 2013-09-23 0intro }
955 6f4d00ee 2013-09-23 0intro deCleanup(&de);
956 6f4d00ee 2013-09-23 0intro fsRsearch1(f, path);
957 6f4d00ee 2013-09-23 0intro fileDecRef(f);
958 6f4d00ee 2013-09-23 0intro return 1;
959 6f4d00ee 2013-09-23 0intro }
960 6f4d00ee 2013-09-23 0intro
961 6f4d00ee 2013-09-23 0intro void
962 6f4d00ee 2013-09-23 0intro fsSnapshotRemove(Fs *fs)
963 6f4d00ee 2013-09-23 0intro {
964 4b576658 2013-09-23 0intro rlock(&fs->elk);
965 6f4d00ee 2013-09-23 0intro fsRsearch(fs, "/snapshot");
966 4b576658 2013-09-23 0intro runlock(&fs->elk);
967 6f4d00ee 2013-09-23 0intro }
968 6f4d00ee 2013-09-23 0intro
969 6f4d00ee 2013-09-23 0intro struct Snap
970 6f4d00ee 2013-09-23 0intro {
971 6f4d00ee 2013-09-23 0intro Fs *fs;
972 6f4d00ee 2013-09-23 0intro Periodic*tick;
973 4b576658 2013-09-23 0intro QLock lk;
974 6f4d00ee 2013-09-23 0intro uint snapMinutes;
975 6f4d00ee 2013-09-23 0intro uint archMinute;
976 6f4d00ee 2013-09-23 0intro uint snapLife;
977 6f4d00ee 2013-09-23 0intro u32int lastSnap;
978 6f4d00ee 2013-09-23 0intro u32int lastArch;
979 6f4d00ee 2013-09-23 0intro u32int lastCleanup;
980 6f4d00ee 2013-09-23 0intro uint ignore;
981 6f4d00ee 2013-09-23 0intro };
982 6f4d00ee 2013-09-23 0intro
983 6f4d00ee 2013-09-23 0intro static void
984 6f4d00ee 2013-09-23 0intro snapEvent(void *v)
985 6f4d00ee 2013-09-23 0intro {
986 6f4d00ee 2013-09-23 0intro Snap *s;
987 6f4d00ee 2013-09-23 0intro u32int now, min;
988 6f4d00ee 2013-09-23 0intro Tm tm;
989 6f4d00ee 2013-09-23 0intro int need;
990 6f4d00ee 2013-09-23 0intro u32int snaplife;
991 6f4d00ee 2013-09-23 0intro
992 6f4d00ee 2013-09-23 0intro s = v;
993 6f4d00ee 2013-09-23 0intro
994 6f4d00ee 2013-09-23 0intro now = time(0)/60;
995 4b576658 2013-09-23 0intro qlock(&s->lk);
996 6f4d00ee 2013-09-23 0intro
997 6f4d00ee 2013-09-23 0intro /*
998 6f4d00ee 2013-09-23 0intro * Snapshots happen every snapMinutes minutes.
999 6f4d00ee 2013-09-23 0intro * If we miss a snapshot (for example, because we
1000 6f4d00ee 2013-09-23 0intro * were down), we wait for the next one.
1001 6f4d00ee 2013-09-23 0intro */
1002 6f4d00ee 2013-09-23 0intro if(s->snapMinutes != ~0 && s->snapMinutes != 0
1003 6f4d00ee 2013-09-23 0intro && now%s->snapMinutes==0 && now != s->lastSnap){
1004 6f4d00ee 2013-09-23 0intro if(!fsSnapshot(s->fs, nil, nil, 0))
1005 4b576658 2013-09-23 0intro fprint(2, "%s: fsSnapshot snap: %r\n", argv0);
1006 6f4d00ee 2013-09-23 0intro s->lastSnap = now;
1007 6f4d00ee 2013-09-23 0intro }
1008 6f4d00ee 2013-09-23 0intro
1009 6f4d00ee 2013-09-23 0intro /*
1010 6f4d00ee 2013-09-23 0intro * Archival snapshots happen at archMinute.
1011 6f4d00ee 2013-09-23 0intro * If we miss an archive (for example, because we
1012 6f4d00ee 2013-09-23 0intro * were down), we do it as soon as possible.
1013 6f4d00ee 2013-09-23 0intro */
1014 6f4d00ee 2013-09-23 0intro tm = *localtime(now*60);
1015 6f4d00ee 2013-09-23 0intro min = tm.hour*60+tm.min;
1016 6f4d00ee 2013-09-23 0intro if(s->archMinute != ~0){
1017 6f4d00ee 2013-09-23 0intro need = 0;
1018 6f4d00ee 2013-09-23 0intro if(min == s->archMinute && now != s->lastArch)
1019 6f4d00ee 2013-09-23 0intro need = 1;
1020 6f4d00ee 2013-09-23 0intro if(s->lastArch == 0){
1021 6f4d00ee 2013-09-23 0intro s->lastArch = 1;
1022 6f4d00ee 2013-09-23 0intro if(fsNeedArch(s->fs, s->archMinute))
1023 6f4d00ee 2013-09-23 0intro need = 1;
1024 6f4d00ee 2013-09-23 0intro }
1025 6f4d00ee 2013-09-23 0intro if(need){
1026 6f4d00ee 2013-09-23 0intro fsSnapshot(s->fs, nil, nil, 1);
1027 6f4d00ee 2013-09-23 0intro s->lastArch = now;
1028 6f4d00ee 2013-09-23 0intro }
1029 6f4d00ee 2013-09-23 0intro }
1030 6f4d00ee 2013-09-23 0intro
1031 6f4d00ee 2013-09-23 0intro /*
1032 6f4d00ee 2013-09-23 0intro * Snapshot cleanup happens every snaplife or every day.
1033 6f4d00ee 2013-09-23 0intro */
1034 6f4d00ee 2013-09-23 0intro snaplife = s->snapLife;
1035 6f4d00ee 2013-09-23 0intro if(snaplife == ~0)
1036 6f4d00ee 2013-09-23 0intro snaplife = 24*60;
1037 6f4d00ee 2013-09-23 0intro if(s->lastCleanup+snaplife < now){
1038 6f4d00ee 2013-09-23 0intro fsSnapshotCleanup(s->fs, s->snapLife);
1039 6f4d00ee 2013-09-23 0intro s->lastCleanup = now;
1040 6f4d00ee 2013-09-23 0intro }
1041 4b576658 2013-09-23 0intro qunlock(&s->lk);
1042 6f4d00ee 2013-09-23 0intro }
1043 6f4d00ee 2013-09-23 0intro
1044 6f4d00ee 2013-09-23 0intro static Snap*
1045 6f4d00ee 2013-09-23 0intro snapInit(Fs *fs)
1046 6f4d00ee 2013-09-23 0intro {
1047 6f4d00ee 2013-09-23 0intro Snap *s;
1048 6f4d00ee 2013-09-23 0intro
1049 4b576658 2013-09-23 0intro s = vtmallocz(sizeof(Snap));
1050 6f4d00ee 2013-09-23 0intro s->fs = fs;
1051 6f4d00ee 2013-09-23 0intro s->tick = periodicAlloc(snapEvent, s, 10*1000);
1052 6f4d00ee 2013-09-23 0intro s->snapMinutes = -1;
1053 6f4d00ee 2013-09-23 0intro s->archMinute = -1;
1054 6f4d00ee 2013-09-23 0intro s->snapLife = -1;
1055 6f4d00ee 2013-09-23 0intro s->ignore = 5*2; /* wait five minutes for clock to stabilize */
1056 6f4d00ee 2013-09-23 0intro return s;
1057 6f4d00ee 2013-09-23 0intro }
1058 6f4d00ee 2013-09-23 0intro
1059 6f4d00ee 2013-09-23 0intro void
1060 6f4d00ee 2013-09-23 0intro snapGetTimes(Snap *s, u32int *arch, u32int *snap, u32int *snaplen)
1061 6f4d00ee 2013-09-23 0intro {
1062 6f4d00ee 2013-09-23 0intro if(s == nil){
1063 6f4d00ee 2013-09-23 0intro *snap = -1;
1064 6f4d00ee 2013-09-23 0intro *arch = -1;
1065 6f4d00ee 2013-09-23 0intro *snaplen = -1;
1066 6f4d00ee 2013-09-23 0intro return;
1067 6f4d00ee 2013-09-23 0intro }
1068 6f4d00ee 2013-09-23 0intro
1069 4b576658 2013-09-23 0intro qlock(&s->lk);
1070 6f4d00ee 2013-09-23 0intro *snap = s->snapMinutes;
1071 6f4d00ee 2013-09-23 0intro *arch = s->archMinute;
1072 6f4d00ee 2013-09-23 0intro *snaplen = s->snapLife;
1073 4b576658 2013-09-23 0intro qunlock(&s->lk);
1074 6f4d00ee 2013-09-23 0intro }
1075 6f4d00ee 2013-09-23 0intro
1076 6f4d00ee 2013-09-23 0intro void
1077 6f4d00ee 2013-09-23 0intro snapSetTimes(Snap *s, u32int arch, u32int snap, u32int snaplen)
1078 6f4d00ee 2013-09-23 0intro {
1079 6f4d00ee 2013-09-23 0intro if(s == nil)
1080 6f4d00ee 2013-09-23 0intro return;
1081 6f4d00ee 2013-09-23 0intro
1082 4b576658 2013-09-23 0intro qlock(&s->lk);
1083 6f4d00ee 2013-09-23 0intro s->snapMinutes = snap;
1084 6f4d00ee 2013-09-23 0intro s->archMinute = arch;
1085 6f4d00ee 2013-09-23 0intro s->snapLife = snaplen;
1086 4b576658 2013-09-23 0intro qunlock(&s->lk);
1087 6f4d00ee 2013-09-23 0intro }
1088 6f4d00ee 2013-09-23 0intro
1089 6f4d00ee 2013-09-23 0intro static void
1090 6f4d00ee 2013-09-23 0intro snapClose(Snap *s)
1091 6f4d00ee 2013-09-23 0intro {
1092 6f4d00ee 2013-09-23 0intro if(s == nil)
1093 6f4d00ee 2013-09-23 0intro return;
1094 6f4d00ee 2013-09-23 0intro
1095 6f4d00ee 2013-09-23 0intro periodicKill(s->tick);
1096 4b576658 2013-09-23 0intro vtfree(s);
1097 6f4d00ee 2013-09-23 0intro }