xref: /plan9/sys/src/cmd/disk/kfs/dentry.c (revision 229d2d344532463b8438213e6bf550fed5babd4a)
1 #include	"all.h"
2 
3 Dentry*
getdir(Iobuf * p,int slot)4 getdir(Iobuf *p, int slot)
5 {
6 	Dentry *d;
7 
8 	if(!p)
9 		return 0;
10 	d = (Dentry*)p->iobuf + slot%DIRPERBUF;
11 	return d;
12 }
13 
14 void
accessdir(Iobuf * p,Dentry * d,int f)15 accessdir(Iobuf *p, Dentry *d, int f)
16 {
17 	long t;
18 
19 	if(p && !isro(p->dev)) {
20 		if(!(f & (FWRITE|FWSTAT)) && noatime)
21 			return;
22 		t = time(nil);
23 		if(f & (FREAD|FWRITE|FWSTAT)){
24 			d->atime = t;
25 			p->flags |= Bmod;
26 		}
27 		if(f & FWRITE) {
28 			d->mtime = t;
29 			d->qid.version++;
30 			p->flags |= Bmod;
31 		}
32 	}
33 }
34 
35 void
dbufread(Iobuf * p,Dentry * d,long a)36 dbufread(Iobuf *p, Dentry *d, long a)
37 {
38 	USED(p, d, a);
39 }
40 
41 long
rel2abs(Iobuf * p,Dentry * d,long a,int tag,int putb)42 rel2abs(Iobuf *p, Dentry *d, long a, int tag, int putb)
43 {
44 	long addr, qpath;
45 	Device dev;
46 
47 	if(a < 0) {
48 		print("dnodebuf: neg\n");
49 		return 0;
50 	}
51 	qpath = d->qid.path;
52 	dev = p->dev;
53 	if(a < NDBLOCK) {
54 		addr = d->dblock[a];
55 		if(!addr && tag) {
56 			addr = balloc(dev, tag, qpath);
57 			d->dblock[a] = addr;
58 			p->flags |= Bmod|Bimm;
59 		}
60 		if(putb)
61 			putbuf(p);
62 		return addr;
63 	}
64 	a -= NDBLOCK;
65 	if(a < INDPERBUF) {
66 		addr = d->iblock;
67 		if(!addr && tag) {
68 			addr = balloc(dev, Tind1, qpath);
69 			d->iblock = addr;
70 			p->flags |= Bmod|Bimm;
71 		}
72 		if(putb)
73 			putbuf(p);
74 		addr = indfetch(p, d, addr, a, Tind1, tag);
75 		return addr;
76 	}
77 	a -= INDPERBUF;
78 	if(a < INDPERBUF2) {
79 		addr = d->diblock;
80 		if(!addr && tag) {
81 			addr = balloc(dev, Tind2, qpath);
82 			d->diblock = addr;
83 			p->flags |= Bmod|Bimm;
84 		}
85 		if(putb)
86 			putbuf(p);
87 		addr = indfetch(p, d, addr, a/INDPERBUF, Tind2, Tind1);
88 		addr = indfetch(p, d, addr, a%INDPERBUF, Tind1, tag);
89 		return addr;
90 	}
91 	if(putb)
92 		putbuf(p);
93 	print("dnodebuf: trip indirect\n");
94 	return 0;
95 }
96 
97 Iobuf*
dnodebuf(Iobuf * p,Dentry * d,long a,int tag)98 dnodebuf(Iobuf *p, Dentry *d, long a, int tag)
99 {
100 	long addr;
101 
102 	addr = rel2abs(p, d, a, tag, 0);
103 	if(addr)
104 		return getbuf(p->dev, addr, Bread);
105 	return 0;
106 }
107 
108 /*
109  * same as dnodebuf but it calls putpuf(p)
110  * to reduce interference.
111  */
112 Iobuf*
dnodebuf1(Iobuf * p,Dentry * d,long a,int tag)113 dnodebuf1(Iobuf *p, Dentry *d, long a, int tag)
114 {
115 	long addr;
116 	Device dev;
117 
118 	dev = p->dev;
119 	addr = rel2abs(p, d, a, tag, 1);
120 	if(addr)
121 		return getbuf(dev, addr, Bread);
122 	return 0;
123 
124 }
125 
126 long
indfetch(Iobuf * p,Dentry * d,long addr,long a,int itag,int tag)127 indfetch(Iobuf *p, Dentry *d, long addr, long a, int itag, int tag)
128 {
129 	Iobuf *bp;
130 
131 	if(!addr)
132 		return 0;
133 	bp = getbuf(p->dev, addr, Bread);
134 	if(!bp || checktag(bp, itag, d->qid.path)) {
135 		if(!bp) {
136 			print("ind fetch bp = 0\n");
137 			return 0;
138 		}
139 		print("ind fetch tag\n");
140 		putbuf(bp);
141 		return 0;
142 	}
143 	addr = ((long*)bp->iobuf)[a];
144 	if(!addr && tag) {
145 		addr = balloc(p->dev, tag, d->qid.path);
146 		if(addr) {
147 			((long*)bp->iobuf)[a] = addr;
148 			bp->flags |= Bmod;
149 			if(localfs || tag == Tdir)
150 				bp->flags |= Bimm;
151 			settag(bp, itag, d->qid.path);
152 		}
153 	}
154 	putbuf(bp);
155 	return addr;
156 }
157 
158 void
dtrunc(Iobuf * p,Dentry * d)159 dtrunc(Iobuf *p, Dentry *d)
160 {
161 	int i;
162 
163 	bfree(p->dev, d->diblock, 2);
164 	d->diblock = 0;
165 	bfree(p->dev, d->iblock, 1);
166 	d->iblock = 0;
167 	for(i=NDBLOCK-1; i>=0; i--) {
168 		bfree(p->dev, d->dblock[i], 0);
169 		d->dblock[i] = 0;
170 	}
171 	d->size = 0;
172 	p->flags |= Bmod|Bimm;
173 	accessdir(p, d, FWRITE);
174 }
175