xref: /haiku/src/add-ons/kernel/file_systems/fat/vcache.cpp (revision 9f3ba01bd36e8069a3550fb10c38c48841a2c0bc)
1*9f3ba01bSAlexander von Gluck IV /*
2*9f3ba01bSAlexander von Gluck IV 	Copyright 1999-2001, Be Incorporated.   All Rights Reserved.
3*9f3ba01bSAlexander von Gluck IV 	This file may be used under the terms of the Be Sample Code License.
4*9f3ba01bSAlexander von Gluck IV */
5*9f3ba01bSAlexander von Gluck IV /*
6*9f3ba01bSAlexander von Gluck IV The FAT file system has no good way of assigning unique persistent values to
7*9f3ba01bSAlexander von Gluck IV nodes. The only obvious choice, storing the starting cluster number of the
8*9f3ba01bSAlexander von Gluck IV file, is unusable because 0 byte files exist as directory entries only.
9*9f3ba01bSAlexander von Gluck IV Further, even if it were usable, it would potentially require a full directory
10*9f3ba01bSAlexander von Gluck IV tree traversal to locate an arbitrary node. We must resort to some ickiness
11*9f3ba01bSAlexander von Gluck IV in order to make persistent vnode id's (at least across a given mount) work.
12*9f3ba01bSAlexander von Gluck IV 
13*9f3ba01bSAlexander von Gluck IV There are three ways to encode a vnode id:
14*9f3ba01bSAlexander von Gluck IV 
15*9f3ba01bSAlexander von Gluck IV 1. Combine the starting cluster of the entry with the starting cluster of the
16*9f3ba01bSAlexander von Gluck IV    directory it appears in. This is used for files with data.
17*9f3ba01bSAlexander von Gluck IV 2. Combine the starting cluster of the directory the entry appears in with the
18*9f3ba01bSAlexander von Gluck IV    index of the entry in the directory. This is used for 0-byte files.
19*9f3ba01bSAlexander von Gluck IV 3. A unique number that doesn't match any possible values from encodings 1 or
20*9f3ba01bSAlexander von Gluck IV    2.
21*9f3ba01bSAlexander von Gluck IV 
22*9f3ba01bSAlexander von Gluck IV With the first encoding, the vnode id is invalidated (i.e. no longer describes
23*9f3ba01bSAlexander von Gluck IV the file's location) when the file moves to a different directory or when
24*9f3ba01bSAlexander von Gluck IV its starting cluster changes (this can occur if the file is truncated and data
25*9f3ba01bSAlexander von Gluck IV is subsequently written to it).
26*9f3ba01bSAlexander von Gluck IV 
27*9f3ba01bSAlexander von Gluck IV With the second encoding, the vnode id is invalidated when the file position
28*9f3ba01bSAlexander von Gluck IV is moved within a directory (as a result of a renaming), when it's moved to a
29*9f3ba01bSAlexander von Gluck IV different directory, or when data is written to it.
30*9f3ba01bSAlexander von Gluck IV 
31*9f3ba01bSAlexander von Gluck IV The third encoding doesn't describe the file's location on disk, and so it is
32*9f3ba01bSAlexander von Gluck IV invalid from the start.
33*9f3ba01bSAlexander von Gluck IV 
34*9f3ba01bSAlexander von Gluck IV Since we can't change vnode id's once they are assigned, we have to create a
35*9f3ba01bSAlexander von Gluck IV mapping table to translate vnode id's to locations. This file serves this
36*9f3ba01bSAlexander von Gluck IV purpose.
37*9f3ba01bSAlexander von Gluck IV */
38*9f3ba01bSAlexander von Gluck IV 
39*9f3ba01bSAlexander von Gluck IV 
40*9f3ba01bSAlexander von Gluck IV #include "vcache.h"
41*9f3ba01bSAlexander von Gluck IV 
42*9f3ba01bSAlexander von Gluck IV #include "system_dependencies.h"
43*9f3ba01bSAlexander von Gluck IV 
44*9f3ba01bSAlexander von Gluck IV #include "dosfs.h"
45*9f3ba01bSAlexander von Gluck IV #include "util.h"
46*9f3ba01bSAlexander von Gluck IV 
47*9f3ba01bSAlexander von Gluck IV 
48*9f3ba01bSAlexander von Gluck IV #define DPRINTF(a,b) if (debug_vcache > (a)) dprintf b
49*9f3ba01bSAlexander von Gluck IV 
50*9f3ba01bSAlexander von Gluck IV #define LOCK_CACHE_R \
51*9f3ba01bSAlexander von Gluck IV 	rw_lock_read_lock(&vol->vcache.lock)
52*9f3ba01bSAlexander von Gluck IV 
53*9f3ba01bSAlexander von Gluck IV #define LOCK_CACHE_W \
54*9f3ba01bSAlexander von Gluck IV 	rw_lock_write_lock(&vol->vcache.lock)
55*9f3ba01bSAlexander von Gluck IV 
56*9f3ba01bSAlexander von Gluck IV #define UNLOCK_CACHE_R \
57*9f3ba01bSAlexander von Gluck IV 	rw_lock_read_unlock(&vol->vcache.lock)
58*9f3ba01bSAlexander von Gluck IV 
59*9f3ba01bSAlexander von Gluck IV #define UNLOCK_CACHE_W \
60*9f3ba01bSAlexander von Gluck IV 	rw_lock_write_unlock(&vol->vcache.lock)
61*9f3ba01bSAlexander von Gluck IV 
62*9f3ba01bSAlexander von Gluck IV #define hash(v) ((v) & (vol->vcache.cache_size-1))
63*9f3ba01bSAlexander von Gluck IV 
64*9f3ba01bSAlexander von Gluck IV 
65*9f3ba01bSAlexander von Gluck IV struct vcache_entry {
66*9f3ba01bSAlexander von Gluck IV 	ino_t	vnid;		/* originally reported vnid */
67*9f3ba01bSAlexander von Gluck IV 	ino_t	loc;		/* where the file is now */
68*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *next_vnid; /* next entry in vnid hash table */
69*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *next_loc;  /* next entry in location hash table */
70*9f3ba01bSAlexander von Gluck IV };
71*9f3ba01bSAlexander von Gluck IV 
72*9f3ba01bSAlexander von Gluck IV 
73*9f3ba01bSAlexander von Gluck IV void
74*9f3ba01bSAlexander von Gluck IV dump_vcache(nspace *vol)
75*9f3ba01bSAlexander von Gluck IV {
76*9f3ba01bSAlexander von Gluck IV 	uint32 i;
77*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *c;
78*9f3ba01bSAlexander von Gluck IV 	kprintf("vnid cache size %" B_PRIu32 ", cur vnid = %" B_PRIdINO "\n"
79*9f3ba01bSAlexander von Gluck IV 		"vnid             loc\n", vol->vcache.cache_size, vol->vcache.cur_vnid);
80*9f3ba01bSAlexander von Gluck IV 	for (i = 0; i < vol->vcache.cache_size; i++) {
81*9f3ba01bSAlexander von Gluck IV 		for (c = vol->vcache.by_vnid[i]; c ; c = c->next_vnid)
82*9f3ba01bSAlexander von Gluck IV 			kprintf("%16" B_PRIdINO " %16" B_PRIdINO "\n", c->vnid, c->loc);
83*9f3ba01bSAlexander von Gluck IV 	}
84*9f3ba01bSAlexander von Gluck IV }
85*9f3ba01bSAlexander von Gluck IV 
86*9f3ba01bSAlexander von Gluck IV 
87*9f3ba01bSAlexander von Gluck IV status_t
88*9f3ba01bSAlexander von Gluck IV init_vcache(nspace *vol)
89*9f3ba01bSAlexander von Gluck IV {
90*9f3ba01bSAlexander von Gluck IV 	char name[16];
91*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("init_vcache called\n"));
92*9f3ba01bSAlexander von Gluck IV 
93*9f3ba01bSAlexander von Gluck IV 	vol->vcache.cur_vnid = ARTIFICIAL_VNID_BITS;
94*9f3ba01bSAlexander von Gluck IV #if DEBUG
95*9f3ba01bSAlexander von Gluck IV 	vol->vcache.cache_size = 1;
96*9f3ba01bSAlexander von Gluck IV #else
97*9f3ba01bSAlexander von Gluck IV 	vol->vcache.cache_size = 512; /* must be power of 2 */
98*9f3ba01bSAlexander von Gluck IV #endif
99*9f3ba01bSAlexander von Gluck IV 
100*9f3ba01bSAlexander von Gluck IV 	vol->vcache.by_vnid = (vcache_entry**)calloc(sizeof(struct vache_entry *),
101*9f3ba01bSAlexander von Gluck IV 		vol->vcache.cache_size);
102*9f3ba01bSAlexander von Gluck IV 	if (vol->vcache.by_vnid == NULL) {
103*9f3ba01bSAlexander von Gluck IV 		dprintf("init_vcache: out of memory\n");
104*9f3ba01bSAlexander von Gluck IV 		return ENOMEM;
105*9f3ba01bSAlexander von Gluck IV 	}
106*9f3ba01bSAlexander von Gluck IV 
107*9f3ba01bSAlexander von Gluck IV 	vol->vcache.by_loc = (vcache_entry**)calloc(sizeof(struct vache_entry *),
108*9f3ba01bSAlexander von Gluck IV 		vol->vcache.cache_size);
109*9f3ba01bSAlexander von Gluck IV 	if (vol->vcache.by_loc == NULL) {
110*9f3ba01bSAlexander von Gluck IV 		dprintf("init_vcache: out of memory\n");
111*9f3ba01bSAlexander von Gluck IV 		free(vol->vcache.by_vnid);
112*9f3ba01bSAlexander von Gluck IV 		vol->vcache.by_vnid = NULL;
113*9f3ba01bSAlexander von Gluck IV 		return ENOMEM;
114*9f3ba01bSAlexander von Gluck IV 	}
115*9f3ba01bSAlexander von Gluck IV 
116*9f3ba01bSAlexander von Gluck IV 	sprintf(name, "fat cache %" B_PRIdDEV, vol->id);
117*9f3ba01bSAlexander von Gluck IV 	rw_lock_init(&vol->vcache.lock, "fat cache");
118*9f3ba01bSAlexander von Gluck IV 
119*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("init_vcache: initialized vnid cache with %" B_PRIu32
120*9f3ba01bSAlexander von Gluck IV 		" entries\n", vol->vcache.cache_size));
121*9f3ba01bSAlexander von Gluck IV 
122*9f3ba01bSAlexander von Gluck IV 	return 0;
123*9f3ba01bSAlexander von Gluck IV }
124*9f3ba01bSAlexander von Gluck IV 
125*9f3ba01bSAlexander von Gluck IV 
126*9f3ba01bSAlexander von Gluck IV status_t
127*9f3ba01bSAlexander von Gluck IV uninit_vcache(nspace *vol)
128*9f3ba01bSAlexander von Gluck IV {
129*9f3ba01bSAlexander von Gluck IV 	uint32 i, count = 0;
130*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *c, *n;
131*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("uninit_vcache called\n"));
132*9f3ba01bSAlexander von Gluck IV 
133*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_W;
134*9f3ba01bSAlexander von Gluck IV 
135*9f3ba01bSAlexander von Gluck IV 	/* free entries */
136*9f3ba01bSAlexander von Gluck IV 	for (i = 0; i < vol->vcache.cache_size; i++) {
137*9f3ba01bSAlexander von Gluck IV 		c = vol->vcache.by_vnid[i];
138*9f3ba01bSAlexander von Gluck IV 		while (c) {
139*9f3ba01bSAlexander von Gluck IV 			count++;
140*9f3ba01bSAlexander von Gluck IV 			n = c->next_vnid;
141*9f3ba01bSAlexander von Gluck IV 			free(c);
142*9f3ba01bSAlexander von Gluck IV 			c = n;
143*9f3ba01bSAlexander von Gluck IV 		}
144*9f3ba01bSAlexander von Gluck IV 	}
145*9f3ba01bSAlexander von Gluck IV 
146*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("%" B_PRIu32 " vcache entries removed\n", count));
147*9f3ba01bSAlexander von Gluck IV 
148*9f3ba01bSAlexander von Gluck IV 	free(vol->vcache.by_vnid); vol->vcache.by_vnid = NULL;
149*9f3ba01bSAlexander von Gluck IV 	free(vol->vcache.by_loc); vol->vcache.by_loc = NULL;
150*9f3ba01bSAlexander von Gluck IV 
151*9f3ba01bSAlexander von Gluck IV 	rw_lock_destroy(&vol->vcache.lock);
152*9f3ba01bSAlexander von Gluck IV 	return B_OK;
153*9f3ba01bSAlexander von Gluck IV }
154*9f3ba01bSAlexander von Gluck IV 
155*9f3ba01bSAlexander von Gluck IV 
156*9f3ba01bSAlexander von Gluck IV ino_t
157*9f3ba01bSAlexander von Gluck IV generate_unique_vnid(nspace *vol)
158*9f3ba01bSAlexander von Gluck IV {
159*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("generate_unique_vnid\n"));
160*9f3ba01bSAlexander von Gluck IV 	/* only one thread per volume will be in here at any given time anyway
161*9f3ba01bSAlexander von Gluck IV 	 * due to volume locking */
162*9f3ba01bSAlexander von Gluck IV 	return vol->vcache.cur_vnid++;
163*9f3ba01bSAlexander von Gluck IV }
164*9f3ba01bSAlexander von Gluck IV 
165*9f3ba01bSAlexander von Gluck IV 
166*9f3ba01bSAlexander von Gluck IV static status_t
167*9f3ba01bSAlexander von Gluck IV _add_to_vcache_(nspace *vol, ino_t vnid, ino_t loc)
168*9f3ba01bSAlexander von Gluck IV {
169*9f3ba01bSAlexander von Gluck IV 	int hash1 = hash(vnid), hash2 = hash(loc);
170*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *e, *c, *p;
171*9f3ba01bSAlexander von Gluck IV 
172*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("add_to_vcache %" B_PRIdINO "/%" B_PRIdINO "\n", vnid, loc));
173*9f3ba01bSAlexander von Gluck IV 
174*9f3ba01bSAlexander von Gluck IV 	ASSERT(vnid != loc);
175*9f3ba01bSAlexander von Gluck IV 
176*9f3ba01bSAlexander von Gluck IV 	e = (vcache_entry*)malloc(sizeof(struct vcache_entry));
177*9f3ba01bSAlexander von Gluck IV 	if (e == NULL)
178*9f3ba01bSAlexander von Gluck IV 		return ENOMEM;
179*9f3ba01bSAlexander von Gluck IV 
180*9f3ba01bSAlexander von Gluck IV 	e->vnid = vnid; e->loc = loc; e->next_vnid = NULL; e->next_loc = NULL;
181*9f3ba01bSAlexander von Gluck IV 
182*9f3ba01bSAlexander von Gluck IV 	c = p = vol->vcache.by_vnid[hash1];
183*9f3ba01bSAlexander von Gluck IV 	while (c) {
184*9f3ba01bSAlexander von Gluck IV 		if (vnid < c->vnid)
185*9f3ba01bSAlexander von Gluck IV 			break;
186*9f3ba01bSAlexander von Gluck IV 		ASSERT(vnid != c->vnid); ASSERT(loc != c->loc);
187*9f3ba01bSAlexander von Gluck IV 		p = c;
188*9f3ba01bSAlexander von Gluck IV 		c = c->next_vnid;
189*9f3ba01bSAlexander von Gluck IV 	}
190*9f3ba01bSAlexander von Gluck IV 	ASSERT(!c || (vnid != c->vnid));
191*9f3ba01bSAlexander von Gluck IV 
192*9f3ba01bSAlexander von Gluck IV 	e->next_vnid = c;
193*9f3ba01bSAlexander von Gluck IV 	if (p == c)
194*9f3ba01bSAlexander von Gluck IV 		vol->vcache.by_vnid[hash1] = e;
195*9f3ba01bSAlexander von Gluck IV 	else
196*9f3ba01bSAlexander von Gluck IV 		p->next_vnid = e;
197*9f3ba01bSAlexander von Gluck IV 
198*9f3ba01bSAlexander von Gluck IV 	c = p = vol->vcache.by_loc[hash2];
199*9f3ba01bSAlexander von Gluck IV 	while (c) {
200*9f3ba01bSAlexander von Gluck IV 		if (loc < c->loc)
201*9f3ba01bSAlexander von Gluck IV 			break;
202*9f3ba01bSAlexander von Gluck IV 		ASSERT(vnid != c->vnid); ASSERT(loc != c->loc);
203*9f3ba01bSAlexander von Gluck IV 		p = c;
204*9f3ba01bSAlexander von Gluck IV 		c = c->next_loc;
205*9f3ba01bSAlexander von Gluck IV 	}
206*9f3ba01bSAlexander von Gluck IV 	ASSERT(!c || (loc != c->loc));
207*9f3ba01bSAlexander von Gluck IV 
208*9f3ba01bSAlexander von Gluck IV 	e->next_loc = c;
209*9f3ba01bSAlexander von Gluck IV 	if (p == c)
210*9f3ba01bSAlexander von Gluck IV 		vol->vcache.by_loc[hash2] = e;
211*9f3ba01bSAlexander von Gluck IV 	else
212*9f3ba01bSAlexander von Gluck IV 		p->next_loc = e;
213*9f3ba01bSAlexander von Gluck IV 
214*9f3ba01bSAlexander von Gluck IV 	return B_OK;
215*9f3ba01bSAlexander von Gluck IV }
216*9f3ba01bSAlexander von Gluck IV 
217*9f3ba01bSAlexander von Gluck IV 
218*9f3ba01bSAlexander von Gluck IV static status_t
219*9f3ba01bSAlexander von Gluck IV _remove_from_vcache_(nspace *vol, ino_t vnid)
220*9f3ba01bSAlexander von Gluck IV {
221*9f3ba01bSAlexander von Gluck IV 	int hash1 = hash(vnid), hash2;
222*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *c, *p, *e;
223*9f3ba01bSAlexander von Gluck IV 
224*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("remove_from_vcache %" B_PRIdINO "\n", vnid));
225*9f3ba01bSAlexander von Gluck IV 
226*9f3ba01bSAlexander von Gluck IV 	c = p = vol->vcache.by_vnid[hash1];
227*9f3ba01bSAlexander von Gluck IV 	while (c) {
228*9f3ba01bSAlexander von Gluck IV 		if (vnid == c->vnid)
229*9f3ba01bSAlexander von Gluck IV 			break;
230*9f3ba01bSAlexander von Gluck IV 		ASSERT(c->vnid < vnid);
231*9f3ba01bSAlexander von Gluck IV 		p = c;
232*9f3ba01bSAlexander von Gluck IV 		c = c->next_vnid;
233*9f3ba01bSAlexander von Gluck IV 	}
234*9f3ba01bSAlexander von Gluck IV 	ASSERT(c);
235*9f3ba01bSAlexander von Gluck IV 	if (!c) return ENOENT;
236*9f3ba01bSAlexander von Gluck IV 
237*9f3ba01bSAlexander von Gluck IV 	if (p == c)
238*9f3ba01bSAlexander von Gluck IV 		vol->vcache.by_vnid[hash1] = c->next_vnid;
239*9f3ba01bSAlexander von Gluck IV 	else
240*9f3ba01bSAlexander von Gluck IV 		p->next_vnid = c->next_vnid;
241*9f3ba01bSAlexander von Gluck IV 
242*9f3ba01bSAlexander von Gluck IV 	e = c;
243*9f3ba01bSAlexander von Gluck IV 
244*9f3ba01bSAlexander von Gluck IV 	hash2 = hash(c->loc);
245*9f3ba01bSAlexander von Gluck IV 	c = p = vol->vcache.by_loc[hash2];
246*9f3ba01bSAlexander von Gluck IV 
247*9f3ba01bSAlexander von Gluck IV 	while (c) {
248*9f3ba01bSAlexander von Gluck IV 		if (vnid == c->vnid)
249*9f3ba01bSAlexander von Gluck IV 			break;
250*9f3ba01bSAlexander von Gluck IV 		ASSERT(c->loc < e->loc);
251*9f3ba01bSAlexander von Gluck IV 		p = c;
252*9f3ba01bSAlexander von Gluck IV 		c = c->next_loc;
253*9f3ba01bSAlexander von Gluck IV 	}
254*9f3ba01bSAlexander von Gluck IV 	ASSERT(c);
255*9f3ba01bSAlexander von Gluck IV 	if (!c) return ENOENT;
256*9f3ba01bSAlexander von Gluck IV 	if (p == c)
257*9f3ba01bSAlexander von Gluck IV 		vol->vcache.by_loc[hash2] = c->next_loc;
258*9f3ba01bSAlexander von Gluck IV 	else
259*9f3ba01bSAlexander von Gluck IV 		p->next_loc = c->next_loc;
260*9f3ba01bSAlexander von Gluck IV 
261*9f3ba01bSAlexander von Gluck IV 	free(c);
262*9f3ba01bSAlexander von Gluck IV 
263*9f3ba01bSAlexander von Gluck IV 	return 0;
264*9f3ba01bSAlexander von Gluck IV }
265*9f3ba01bSAlexander von Gluck IV 
266*9f3ba01bSAlexander von Gluck IV 
267*9f3ba01bSAlexander von Gluck IV static struct vcache_entry *
268*9f3ba01bSAlexander von Gluck IV _find_vnid_in_vcache_(nspace *vol, ino_t vnid)
269*9f3ba01bSAlexander von Gluck IV {
270*9f3ba01bSAlexander von Gluck IV 	int hash1 = hash(vnid);
271*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *c;
272*9f3ba01bSAlexander von Gluck IV 	c = vol->vcache.by_vnid[hash1];
273*9f3ba01bSAlexander von Gluck IV 	while (c) {
274*9f3ba01bSAlexander von Gluck IV 		if (c->vnid == vnid)
275*9f3ba01bSAlexander von Gluck IV 			break;
276*9f3ba01bSAlexander von Gluck IV 		if (c->vnid > vnid)
277*9f3ba01bSAlexander von Gluck IV 			return NULL;
278*9f3ba01bSAlexander von Gluck IV 		c = c->next_vnid;
279*9f3ba01bSAlexander von Gluck IV 	}
280*9f3ba01bSAlexander von Gluck IV 
281*9f3ba01bSAlexander von Gluck IV 	return c;
282*9f3ba01bSAlexander von Gluck IV }
283*9f3ba01bSAlexander von Gluck IV 
284*9f3ba01bSAlexander von Gluck IV 
285*9f3ba01bSAlexander von Gluck IV static struct vcache_entry *
286*9f3ba01bSAlexander von Gluck IV _find_loc_in_vcache_(nspace *vol, ino_t loc)
287*9f3ba01bSAlexander von Gluck IV {
288*9f3ba01bSAlexander von Gluck IV 	int hash2 = hash(loc);
289*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *c;
290*9f3ba01bSAlexander von Gluck IV 	c = vol->vcache.by_loc[hash2];
291*9f3ba01bSAlexander von Gluck IV 	while (c) {
292*9f3ba01bSAlexander von Gluck IV 		if (c->loc == loc)
293*9f3ba01bSAlexander von Gluck IV 			break;
294*9f3ba01bSAlexander von Gluck IV 		if (c->loc > loc)
295*9f3ba01bSAlexander von Gluck IV 			return NULL;
296*9f3ba01bSAlexander von Gluck IV 		c = c->next_loc;
297*9f3ba01bSAlexander von Gluck IV 	}
298*9f3ba01bSAlexander von Gluck IV 
299*9f3ba01bSAlexander von Gluck IV 	return c;
300*9f3ba01bSAlexander von Gluck IV }
301*9f3ba01bSAlexander von Gluck IV 
302*9f3ba01bSAlexander von Gluck IV 
303*9f3ba01bSAlexander von Gluck IV status_t
304*9f3ba01bSAlexander von Gluck IV add_to_vcache(nspace *vol, ino_t vnid, ino_t loc)
305*9f3ba01bSAlexander von Gluck IV {
306*9f3ba01bSAlexander von Gluck IV 	status_t result;
307*9f3ba01bSAlexander von Gluck IV 
308*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_W;
309*9f3ba01bSAlexander von Gluck IV 	result = _add_to_vcache_(vol,vnid,loc);
310*9f3ba01bSAlexander von Gluck IV 	UNLOCK_CACHE_W;
311*9f3ba01bSAlexander von Gluck IV 
312*9f3ba01bSAlexander von Gluck IV 	if (result < 0) DPRINTF(0, ("add_to_vcache failed (%s)\n", strerror(result)));
313*9f3ba01bSAlexander von Gluck IV 	return result;
314*9f3ba01bSAlexander von Gluck IV }
315*9f3ba01bSAlexander von Gluck IV 
316*9f3ba01bSAlexander von Gluck IV 
317*9f3ba01bSAlexander von Gluck IV /* XXX: do this in a smarter fashion */
318*9f3ba01bSAlexander von Gluck IV static status_t
319*9f3ba01bSAlexander von Gluck IV _update_loc_in_vcache_(nspace *vol, ino_t vnid, ino_t loc)
320*9f3ba01bSAlexander von Gluck IV {
321*9f3ba01bSAlexander von Gluck IV 	status_t result;
322*9f3ba01bSAlexander von Gluck IV 
323*9f3ba01bSAlexander von Gluck IV 	result = _remove_from_vcache_(vol, vnid);
324*9f3ba01bSAlexander von Gluck IV 	if (result == 0)
325*9f3ba01bSAlexander von Gluck IV 		result = _add_to_vcache_(vol, vnid, loc);
326*9f3ba01bSAlexander von Gluck IV 
327*9f3ba01bSAlexander von Gluck IV 	return result;
328*9f3ba01bSAlexander von Gluck IV }
329*9f3ba01bSAlexander von Gluck IV 
330*9f3ba01bSAlexander von Gluck IV 
331*9f3ba01bSAlexander von Gluck IV status_t
332*9f3ba01bSAlexander von Gluck IV remove_from_vcache(nspace *vol, ino_t vnid)
333*9f3ba01bSAlexander von Gluck IV {
334*9f3ba01bSAlexander von Gluck IV 	status_t result;
335*9f3ba01bSAlexander von Gluck IV 
336*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_W;
337*9f3ba01bSAlexander von Gluck IV 	result = _remove_from_vcache_(vol, vnid);
338*9f3ba01bSAlexander von Gluck IV 	UNLOCK_CACHE_W;
339*9f3ba01bSAlexander von Gluck IV 
340*9f3ba01bSAlexander von Gluck IV 	if (result < 0) DPRINTF(0, ("remove_from_vcache failed (%s)\n", strerror(result)));
341*9f3ba01bSAlexander von Gluck IV 	return result;
342*9f3ba01bSAlexander von Gluck IV }
343*9f3ba01bSAlexander von Gluck IV 
344*9f3ba01bSAlexander von Gluck IV 
345*9f3ba01bSAlexander von Gluck IV status_t
346*9f3ba01bSAlexander von Gluck IV vcache_vnid_to_loc(nspace *vol, ino_t vnid, ino_t *loc)
347*9f3ba01bSAlexander von Gluck IV {
348*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *e;
349*9f3ba01bSAlexander von Gluck IV 
350*9f3ba01bSAlexander von Gluck IV 	DPRINTF(1, ("vcache_vnid_to_loc %" B_PRIdINO " %p\n", vnid,
351*9f3ba01bSAlexander von Gluck IV 		loc));
352*9f3ba01bSAlexander von Gluck IV 
353*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_R;
354*9f3ba01bSAlexander von Gluck IV 	e = _find_vnid_in_vcache_(vol, vnid);
355*9f3ba01bSAlexander von Gluck IV 	if (loc && e)
356*9f3ba01bSAlexander von Gluck IV 			*loc = e->loc;
357*9f3ba01bSAlexander von Gluck IV 	UNLOCK_CACHE_R;
358*9f3ba01bSAlexander von Gluck IV 
359*9f3ba01bSAlexander von Gluck IV 	return (e) ? B_OK : ENOENT;
360*9f3ba01bSAlexander von Gluck IV }
361*9f3ba01bSAlexander von Gluck IV 
362*9f3ba01bSAlexander von Gluck IV 
363*9f3ba01bSAlexander von Gluck IV status_t
364*9f3ba01bSAlexander von Gluck IV vcache_loc_to_vnid(nspace *vol, ino_t loc, ino_t *vnid)
365*9f3ba01bSAlexander von Gluck IV {
366*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *e;
367*9f3ba01bSAlexander von Gluck IV 
368*9f3ba01bSAlexander von Gluck IV 	DPRINTF(1, ("vcache_loc_to_vnid %" B_PRIdINO " %p\n", loc,
369*9f3ba01bSAlexander von Gluck IV 		vnid));
370*9f3ba01bSAlexander von Gluck IV 
371*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_R;
372*9f3ba01bSAlexander von Gluck IV 	e = _find_loc_in_vcache_(vol, loc);
373*9f3ba01bSAlexander von Gluck IV 	if (vnid && e)
374*9f3ba01bSAlexander von Gluck IV 			*vnid = e->vnid;
375*9f3ba01bSAlexander von Gluck IV 	UNLOCK_CACHE_R;
376*9f3ba01bSAlexander von Gluck IV 
377*9f3ba01bSAlexander von Gluck IV 	return (e) ? B_OK : ENOENT;
378*9f3ba01bSAlexander von Gluck IV }
379*9f3ba01bSAlexander von Gluck IV 
380*9f3ba01bSAlexander von Gluck IV 
381*9f3ba01bSAlexander von Gluck IV status_t
382*9f3ba01bSAlexander von Gluck IV vcache_set_entry(nspace *vol, ino_t vnid, ino_t loc)
383*9f3ba01bSAlexander von Gluck IV {
384*9f3ba01bSAlexander von Gluck IV 	struct vcache_entry *e;
385*9f3ba01bSAlexander von Gluck IV 	status_t result = B_OK;
386*9f3ba01bSAlexander von Gluck IV 
387*9f3ba01bSAlexander von Gluck IV 	DPRINTF(0, ("vcache_set_entry: %" B_PRIdINO " -> %" B_PRIdINO "\n", vnid,
388*9f3ba01bSAlexander von Gluck IV 		loc));
389*9f3ba01bSAlexander von Gluck IV 
390*9f3ba01bSAlexander von Gluck IV 	/*if (is_vnode_removed(vol->id, vnid) > 0) {
391*9f3ba01bSAlexander von Gluck IV 		if (!IS_ARTIFICIAL_VNID(loc))
392*9f3ba01bSAlexander von Gluck IV 			return B_OK;
393*9f3ba01bSAlexander von Gluck IV 	} else {
394*9f3ba01bSAlexander von Gluck IV 		ASSERT(is_vnode_removed(vol->id, vnid) == 0);
395*9f3ba01bSAlexander von Gluck IV 	}*/
396*9f3ba01bSAlexander von Gluck IV 
397*9f3ba01bSAlexander von Gluck IV 	LOCK_CACHE_W;
398*9f3ba01bSAlexander von Gluck IV 
399*9f3ba01bSAlexander von Gluck IV 	e = _find_vnid_in_vcache_(vol, vnid);
400*9f3ba01bSAlexander von Gluck IV 
401*9f3ba01bSAlexander von Gluck IV 	if (e) {
402*9f3ba01bSAlexander von Gluck IV 		if (e->vnid == loc)
403*9f3ba01bSAlexander von Gluck IV 			result = _remove_from_vcache_(vol, vnid);
404*9f3ba01bSAlexander von Gluck IV 		else
405*9f3ba01bSAlexander von Gluck IV 			result = _update_loc_in_vcache_(vol, vnid, loc);
406*9f3ba01bSAlexander von Gluck IV 	} else {
407*9f3ba01bSAlexander von Gluck IV 		if (vnid != loc)
408*9f3ba01bSAlexander von Gluck IV 			result = _add_to_vcache_(vol,vnid,loc);
409*9f3ba01bSAlexander von Gluck IV 	}
410*9f3ba01bSAlexander von Gluck IV 
411*9f3ba01bSAlexander von Gluck IV 	UNLOCK_CACHE_W;
412*9f3ba01bSAlexander von Gluck IV 
413*9f3ba01bSAlexander von Gluck IV 	return result;
414*9f3ba01bSAlexander von Gluck IV }
415*9f3ba01bSAlexander von Gluck IV 
416*9f3ba01bSAlexander von Gluck IV #if DEBUG
417*9f3ba01bSAlexander von Gluck IV 
418*9f3ba01bSAlexander von Gluck IV int
419*9f3ba01bSAlexander von Gluck IV debug_dfvnid(int argc, char **argv)
420*9f3ba01bSAlexander von Gluck IV {
421*9f3ba01bSAlexander von Gluck IV 	int i;
422*9f3ba01bSAlexander von Gluck IV 	nspace *vol;
423*9f3ba01bSAlexander von Gluck IV 
424*9f3ba01bSAlexander von Gluck IV 	if (argc < 3) {
425*9f3ba01bSAlexander von Gluck IV 		kprintf("dfvnid nspace vnid\n");
426*9f3ba01bSAlexander von Gluck IV 		return B_OK;
427*9f3ba01bSAlexander von Gluck IV 	}
428*9f3ba01bSAlexander von Gluck IV 
429*9f3ba01bSAlexander von Gluck IV 	vol = (nspace *)strtoul(argv[1], NULL, 0);
430*9f3ba01bSAlexander von Gluck IV 	if (vol == NULL)
431*9f3ba01bSAlexander von Gluck IV 		return B_OK;
432*9f3ba01bSAlexander von Gluck IV 
433*9f3ba01bSAlexander von Gluck IV 	for (i = 2; i < argc; i++) {
434*9f3ba01bSAlexander von Gluck IV 		ino_t vnid = strtoull(argv[i], NULL, 0);
435*9f3ba01bSAlexander von Gluck IV 		struct vcache_entry *e;
436*9f3ba01bSAlexander von Gluck IV 		if ((e = _find_vnid_in_vcache_(vol, vnid)) != NULL) {
437*9f3ba01bSAlexander von Gluck IV 			kprintf("vnid %" B_PRIdINO " -> loc %" B_PRIdINO " @ %p\n", vnid,
438*9f3ba01bSAlexander von Gluck IV 				e->loc, e);
439*9f3ba01bSAlexander von Gluck IV 		} else {
440*9f3ba01bSAlexander von Gluck IV 			kprintf("vnid %" B_PRIdINO " not found in vnid cache\n", vnid);
441*9f3ba01bSAlexander von Gluck IV 		}
442*9f3ba01bSAlexander von Gluck IV 	}
443*9f3ba01bSAlexander von Gluck IV 
444*9f3ba01bSAlexander von Gluck IV 	return B_OK;
445*9f3ba01bSAlexander von Gluck IV }
446*9f3ba01bSAlexander von Gluck IV 
447*9f3ba01bSAlexander von Gluck IV 
448*9f3ba01bSAlexander von Gluck IV int
449*9f3ba01bSAlexander von Gluck IV debug_dfloc(int argc, char **argv)
450*9f3ba01bSAlexander von Gluck IV {
451*9f3ba01bSAlexander von Gluck IV 	int i;
452*9f3ba01bSAlexander von Gluck IV 	nspace *vol;
453*9f3ba01bSAlexander von Gluck IV 
454*9f3ba01bSAlexander von Gluck IV 	if (argc < 3) {
455*9f3ba01bSAlexander von Gluck IV 		kprintf("dfloc nspace vnid\n");
456*9f3ba01bSAlexander von Gluck IV 		return B_OK;
457*9f3ba01bSAlexander von Gluck IV 	}
458*9f3ba01bSAlexander von Gluck IV 
459*9f3ba01bSAlexander von Gluck IV 	vol = (nspace *)strtoul(argv[1], NULL, 0);
460*9f3ba01bSAlexander von Gluck IV 	if (vol == NULL)
461*9f3ba01bSAlexander von Gluck IV 		return B_OK;
462*9f3ba01bSAlexander von Gluck IV 
463*9f3ba01bSAlexander von Gluck IV 	for (i = 2; i < argc; i++) {
464*9f3ba01bSAlexander von Gluck IV 		ino_t loc = strtoull(argv[i], NULL, 0);
465*9f3ba01bSAlexander von Gluck IV 		struct vcache_entry *e;
466*9f3ba01bSAlexander von Gluck IV 		if ((e = _find_loc_in_vcache_(vol, loc)) != NULL) {
467*9f3ba01bSAlexander von Gluck IV 			kprintf("loc %" B_PRIdINO " -> vnid %" B_PRIdINO " @ %p\n", loc,
468*9f3ba01bSAlexander von Gluck IV 				e->vnid, e);
469*9f3ba01bSAlexander von Gluck IV 		} else {
470*9f3ba01bSAlexander von Gluck IV 			kprintf("loc %" B_PRIdINO " not found in vnid cache\n", loc);
471*9f3ba01bSAlexander von Gluck IV 		}
472*9f3ba01bSAlexander von Gluck IV 	}
473*9f3ba01bSAlexander von Gluck IV 
474*9f3ba01bSAlexander von Gluck IV 	return B_OK;
475*9f3ba01bSAlexander von Gluck IV }
476*9f3ba01bSAlexander von Gluck IV 
477*9f3ba01bSAlexander von Gluck IV #endif
478