ref: b5d191e8cfa4fac05a02ea309df2541a2652ff23
dir: /tag.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" static u64 addu64ov(u64 a, u64 b) { u64 r = a + b; if (r < a || r < b) return 0; return r; } static u64 mulu64ov(u64 a, u64 b) { u64 r = a * b; if (a != 0 && r/a != b || r < a || r < b) return 0; return r; } /* could use muluvlongov() here but it does not add any value for us raise base to n-th power; n >= 0 */ u64 power(u64 base, int n) { int i; u64 v; v = 1; for(i = 1; i <= n; i++) v = v*base; return v; } /* Each u64 address in this indirect block links to n Tdata/Tdentry blocks */ u64 nperindunit(u16 tag) { if(tag < Tind0 || tag > Tmaxind+1) return 0; return power(Nindperblock, tag-Tind0); } /* * compute BUFSIZE*(Ndblock+INDPERBUF+INDPERBUF²+INDPERBUF³+INDPERBUF⁴ .. upto ^Niblock) * while watching for overflow; in that case, return 0. */ /* extern double pow(double x, double y); *//* return x ^ y (exponentiation) */ /* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */ /* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */ u64 nperiblock(u16 tag) { return nperindunit(tag+1); } /* get the Tindn tag of the block that a reli belongs to */ u8 rel2tind(u64 reli) { u64 maxfortag, tag, i; if(reli < Ndblock){ panic("should not be here"); } reli -= Ndblock; for(tag = Tind0, i = reli; tag <= Tmaxind; tag++){ maxfortag = nperiblock(tag); if(i < maxfortag) break; i -= maxfortag; } return tag; } /* blocks above this index have this tag For example, Tind0 starts from a reli >= 24 Tind1 starts from a reli >= 74 Tind2 starts from a reli >= 3100 */ u64 tagstartreli(u8 tag) { if(tag == Tind0) return Ndblock; else if(tag == Tind1) return Ndblock+Nindperblock; return nperiblock(tag-1)+tagstartreli(tag-1); } u64 maxreli(u8 tag) { return tagstartreli(tag+1)-1; } u64 maxblocks(u8 tag) { return maxreli(tag)+1; }