19f3ba01bSAlexander von Gluck IV /*
2*342a1b22SJim906 * Copyright 1999-2001, Be Incorporated. All Rights Reserved.
3*342a1b22SJim906 * Copyright 2024, Haiku, Inc. All rights reserved.
4*342a1b22SJim906 * This file may be used under the terms of the Be Sample Code License.
59f3ba01bSAlexander von Gluck IV */
6*342a1b22SJim906
7*342a1b22SJim906
89f3ba01bSAlexander von Gluck IV /*
99f3ba01bSAlexander von Gluck IV The FAT file system has no good way of assigning unique persistent values to
109f3ba01bSAlexander von Gluck IV nodes. The only obvious choice, storing the starting cluster number of the
119f3ba01bSAlexander von Gluck IV file, is unusable because 0 byte files exist as directory entries only.
129f3ba01bSAlexander von Gluck IV Further, even if it were usable, it would potentially require a full directory
139f3ba01bSAlexander von Gluck IV tree traversal to locate an arbitrary node. We must resort to some ickiness
149f3ba01bSAlexander von Gluck IV in order to make persistent vnode id's (at least across a given mount) work.
159f3ba01bSAlexander von Gluck IV
169f3ba01bSAlexander von Gluck IV There are three ways to encode a vnode id:
179f3ba01bSAlexander von Gluck IV
189f3ba01bSAlexander von Gluck IV 1. Combine the starting cluster of the entry with the starting cluster of the
199f3ba01bSAlexander von Gluck IV directory it appears in. This is used for files with data.
209f3ba01bSAlexander von Gluck IV 2. Combine the starting cluster of the directory the entry appears in with the
219f3ba01bSAlexander von Gluck IV index of the entry in the directory. This is used for 0-byte files.
229f3ba01bSAlexander von Gluck IV 3. A unique number that doesn't match any possible values from encodings 1 or
239f3ba01bSAlexander von Gluck IV 2.
249f3ba01bSAlexander von Gluck IV
259f3ba01bSAlexander von Gluck IV With the first encoding, the vnode id is invalidated (i.e. no longer describes
269f3ba01bSAlexander von Gluck IV the file's location) when the file moves to a different directory or when
279f3ba01bSAlexander von Gluck IV its starting cluster changes (this can occur if the file is truncated and data
289f3ba01bSAlexander von Gluck IV is subsequently written to it).
299f3ba01bSAlexander von Gluck IV
309f3ba01bSAlexander von Gluck IV With the second encoding, the vnode id is invalidated when the file position
319f3ba01bSAlexander von Gluck IV is moved within a directory (as a result of a renaming), when it's moved to a
329f3ba01bSAlexander von Gluck IV different directory, or when data is written to it.
339f3ba01bSAlexander von Gluck IV
349f3ba01bSAlexander von Gluck IV The third encoding doesn't describe the file's location on disk, and so it is
359f3ba01bSAlexander von Gluck IV invalid from the start.
369f3ba01bSAlexander von Gluck IV
379f3ba01bSAlexander von Gluck IV Since we can't change vnode id's once they are assigned, we have to create a
389f3ba01bSAlexander von Gluck IV mapping table to translate vnode id's to locations. This file serves this
399f3ba01bSAlexander von Gluck IV purpose.
40*342a1b22SJim906
41*342a1b22SJim906 It also allows the FS to check whether a node with a given inode number has been constructed,
42*342a1b22SJim906 without calling get_vnode().
439f3ba01bSAlexander von Gluck IV */
449f3ba01bSAlexander von Gluck IV
459f3ba01bSAlexander von Gluck IV
469f3ba01bSAlexander von Gluck IV #include "vcache.h"
479f3ba01bSAlexander von Gluck IV
48*342a1b22SJim906 #ifdef FS_SHELL
49*342a1b22SJim906 #include "fssh_api_wrapper.h"
50*342a1b22SJim906 #else // !FS_SHELL
51*342a1b22SJim906 #include <new>
52*342a1b22SJim906 #include <stdint.h>
53*342a1b22SJim906 #include <stdio.h>
54*342a1b22SJim906 #include <stdlib.h>
55*342a1b22SJim906 #endif // !FS_SHELL
569f3ba01bSAlexander von Gluck IV
57*342a1b22SJim906 #ifndef FS_SHELL
58*342a1b22SJim906 #include <fs_cache.h>
59*342a1b22SJim906 #include <fs_interface.h>
60*342a1b22SJim906 #endif // !FS_SHELL
61*342a1b22SJim906
62*342a1b22SJim906 #define _KERNEL
63*342a1b22SJim906 #include "sys/vnode.h"
64*342a1b22SJim906
65*342a1b22SJim906 #include "debug.h"
669f3ba01bSAlexander von Gluck IV #include "dosfs.h"
679f3ba01bSAlexander von Gluck IV
689f3ba01bSAlexander von Gluck IV
699f3ba01bSAlexander von Gluck IV #define LOCK_CACHE_R \
709f3ba01bSAlexander von Gluck IV rw_lock_read_lock(&vol->vcache.lock)
719f3ba01bSAlexander von Gluck IV
729f3ba01bSAlexander von Gluck IV #define LOCK_CACHE_W \
739f3ba01bSAlexander von Gluck IV rw_lock_write_lock(&vol->vcache.lock)
749f3ba01bSAlexander von Gluck IV
759f3ba01bSAlexander von Gluck IV #define UNLOCK_CACHE_R \
769f3ba01bSAlexander von Gluck IV rw_lock_read_unlock(&vol->vcache.lock)
779f3ba01bSAlexander von Gluck IV
789f3ba01bSAlexander von Gluck IV #define UNLOCK_CACHE_W \
799f3ba01bSAlexander von Gluck IV rw_lock_write_unlock(&vol->vcache.lock)
809f3ba01bSAlexander von Gluck IV
819f3ba01bSAlexander von Gluck IV #define hash(v) ((v) & (vol->vcache.cache_size-1))
829f3ba01bSAlexander von Gluck IV
839f3ba01bSAlexander von Gluck IV
849f3ba01bSAlexander von Gluck IV struct vcache_entry {
859f3ba01bSAlexander von Gluck IV ino_t vnid; /* originally reported vnid */
869f3ba01bSAlexander von Gluck IV ino_t loc; /* where the file is now */
87*342a1b22SJim906 bool constructed; /* has the node been set up by _dosfs_read_vnode */
889f3ba01bSAlexander von Gluck IV struct vcache_entry *next_vnid; /* next entry in vnid hash table */
899f3ba01bSAlexander von Gluck IV struct vcache_entry *next_loc; /* next entry in location hash table */
90*342a1b22SJim906 #ifdef DEBUG
91*342a1b22SJim906 struct vnode* node;
92*342a1b22SJim906 #endif
939f3ba01bSAlexander von Gluck IV };
949f3ba01bSAlexander von Gluck IV
959f3ba01bSAlexander von Gluck IV
969f3ba01bSAlexander von Gluck IV void
dump_vcache(const mount * vol)97*342a1b22SJim906 dump_vcache(const mount* vol)
989f3ba01bSAlexander von Gluck IV {
999f3ba01bSAlexander von Gluck IV uint32 i;
1009f3ba01bSAlexander von Gluck IV struct vcache_entry *c;
101*342a1b22SJim906 #if defined DEBUG && defined _KERNEL_MODE
102*342a1b22SJim906 kprintf("vnid cache size %" B_PRIu32 ", cur vnid = %" B_PRIdINO "\n"
103*342a1b22SJim906 "vnid loc %-*s\n", vol->vcache.cache_size, vol->vcache.cur_vnid,
104*342a1b22SJim906 B_PRINTF_POINTER_WIDTH, "struct vnode");
105*342a1b22SJim906 for (i = 0; i < vol->vcache.cache_size; i++) {
106*342a1b22SJim906 for (c = vol->vcache.by_vnid[i]; c ; c = c->next_vnid)
107*342a1b22SJim906 kprintf("%19" B_PRIdINO " %16" B_PRIdINO " %p\n", c->vnid, c->loc, c->node);
108*342a1b22SJim906 }
109*342a1b22SJim906 #else
1109f3ba01bSAlexander von Gluck IV kprintf("vnid cache size %" B_PRIu32 ", cur vnid = %" B_PRIdINO "\n"
1119f3ba01bSAlexander von Gluck IV "vnid loc\n", vol->vcache.cache_size, vol->vcache.cur_vnid);
1129f3ba01bSAlexander von Gluck IV for (i = 0; i < vol->vcache.cache_size; i++) {
1139f3ba01bSAlexander von Gluck IV for (c = vol->vcache.by_vnid[i]; c ; c = c->next_vnid)
114*342a1b22SJim906 kprintf("%19" B_PRIdINO " %16" B_PRIdINO "\n", c->vnid, c->loc);
1159f3ba01bSAlexander von Gluck IV }
116*342a1b22SJim906 #endif // !DEBUG
1179f3ba01bSAlexander von Gluck IV }
1189f3ba01bSAlexander von Gluck IV
1199f3ba01bSAlexander von Gluck IV
1209f3ba01bSAlexander von Gluck IV status_t
init_vcache(mount * vol)121*342a1b22SJim906 init_vcache(mount* vol)
1229f3ba01bSAlexander von Gluck IV {
1239f3ba01bSAlexander von Gluck IV char name[16];
124*342a1b22SJim906 FUNCTION();
1259f3ba01bSAlexander von Gluck IV
1269f3ba01bSAlexander von Gluck IV vol->vcache.cur_vnid = ARTIFICIAL_VNID_BITS;
1279f3ba01bSAlexander von Gluck IV #if DEBUG
1289f3ba01bSAlexander von Gluck IV vol->vcache.cache_size = 1;
1299f3ba01bSAlexander von Gluck IV #else
1309f3ba01bSAlexander von Gluck IV vol->vcache.cache_size = 512; /* must be power of 2 */
1319f3ba01bSAlexander von Gluck IV #endif
1329f3ba01bSAlexander von Gluck IV
1339f3ba01bSAlexander von Gluck IV vol->vcache.by_vnid = (vcache_entry**)calloc(sizeof(struct vache_entry *),
1349f3ba01bSAlexander von Gluck IV vol->vcache.cache_size);
1359f3ba01bSAlexander von Gluck IV if (vol->vcache.by_vnid == NULL) {
136*342a1b22SJim906 INFORM("init_vcache: out of memory\n");
1379f3ba01bSAlexander von Gluck IV return ENOMEM;
1389f3ba01bSAlexander von Gluck IV }
1399f3ba01bSAlexander von Gluck IV
1409f3ba01bSAlexander von Gluck IV vol->vcache.by_loc = (vcache_entry**)calloc(sizeof(struct vache_entry *),
1419f3ba01bSAlexander von Gluck IV vol->vcache.cache_size);
1429f3ba01bSAlexander von Gluck IV if (vol->vcache.by_loc == NULL) {
143*342a1b22SJim906 INFORM("init_vcache: out of memory\n");
1449f3ba01bSAlexander von Gluck IV free(vol->vcache.by_vnid);
1459f3ba01bSAlexander von Gluck IV vol->vcache.by_vnid = NULL;
1469f3ba01bSAlexander von Gluck IV return ENOMEM;
1479f3ba01bSAlexander von Gluck IV }
1489f3ba01bSAlexander von Gluck IV
149*342a1b22SJim906 sprintf(name, "fat cache %" B_PRIdDEV, vol->mnt_fsvolume->id);
1509f3ba01bSAlexander von Gluck IV rw_lock_init(&vol->vcache.lock, "fat cache");
1519f3ba01bSAlexander von Gluck IV
152*342a1b22SJim906 PRINT("init_vcache: initialized vnid cache with %" B_PRIu32
153*342a1b22SJim906 " entries\n", vol->vcache.cache_size);
1549f3ba01bSAlexander von Gluck IV
1559f3ba01bSAlexander von Gluck IV return 0;
1569f3ba01bSAlexander von Gluck IV }
1579f3ba01bSAlexander von Gluck IV
1589f3ba01bSAlexander von Gluck IV
1599f3ba01bSAlexander von Gluck IV status_t
uninit_vcache(mount * vol)160*342a1b22SJim906 uninit_vcache(mount* vol)
1619f3ba01bSAlexander von Gluck IV {
1629f3ba01bSAlexander von Gluck IV uint32 i, count = 0;
1639f3ba01bSAlexander von Gluck IV struct vcache_entry *c, *n;
164*342a1b22SJim906 FUNCTION();
1659f3ba01bSAlexander von Gluck IV
1669f3ba01bSAlexander von Gluck IV LOCK_CACHE_W;
1679f3ba01bSAlexander von Gluck IV
1689f3ba01bSAlexander von Gluck IV /* free entries */
1699f3ba01bSAlexander von Gluck IV for (i = 0; i < vol->vcache.cache_size; i++) {
1709f3ba01bSAlexander von Gluck IV c = vol->vcache.by_vnid[i];
1719f3ba01bSAlexander von Gluck IV while (c) {
1729f3ba01bSAlexander von Gluck IV count++;
1739f3ba01bSAlexander von Gluck IV n = c->next_vnid;
1749f3ba01bSAlexander von Gluck IV free(c);
1759f3ba01bSAlexander von Gluck IV c = n;
1769f3ba01bSAlexander von Gluck IV }
1779f3ba01bSAlexander von Gluck IV }
1789f3ba01bSAlexander von Gluck IV
179*342a1b22SJim906 PRINT("%" B_PRIu32 " vcache entries removed\n", count);
1809f3ba01bSAlexander von Gluck IV
1819f3ba01bSAlexander von Gluck IV free(vol->vcache.by_vnid); vol->vcache.by_vnid = NULL;
1829f3ba01bSAlexander von Gluck IV free(vol->vcache.by_loc); vol->vcache.by_loc = NULL;
1839f3ba01bSAlexander von Gluck IV
1849f3ba01bSAlexander von Gluck IV rw_lock_destroy(&vol->vcache.lock);
1859f3ba01bSAlexander von Gluck IV return B_OK;
1869f3ba01bSAlexander von Gluck IV }
1879f3ba01bSAlexander von Gluck IV
1889f3ba01bSAlexander von Gluck IV
1899f3ba01bSAlexander von Gluck IV ino_t
generate_unique_vnid(mount * vol)190*342a1b22SJim906 generate_unique_vnid(mount* vol)
1919f3ba01bSAlexander von Gluck IV {
192*342a1b22SJim906 FUNCTION();
193*342a1b22SJim906
194*342a1b22SJim906 #ifdef FS_SHELL
195*342a1b22SJim906 LOCK_CACHE_W;
196*342a1b22SJim906 ino_t current = vol->vcache.cur_vnid++;
197*342a1b22SJim906 UNLOCK_CACHE_W;
198*342a1b22SJim906
199*342a1b22SJim906 return current;
200*342a1b22SJim906 #else
201*342a1b22SJim906 return atomic_add64(&vol->vcache.cur_vnid, 1);
202*342a1b22SJim906 #endif // !FS_SHELL
2039f3ba01bSAlexander von Gluck IV }
2049f3ba01bSAlexander von Gluck IV
2059f3ba01bSAlexander von Gluck IV
2069f3ba01bSAlexander von Gluck IV static status_t
_add_to_vcache_(mount * vol,ino_t vnid,ino_t loc)207*342a1b22SJim906 _add_to_vcache_(mount* vol, ino_t vnid, ino_t loc)
2089f3ba01bSAlexander von Gluck IV {
2099f3ba01bSAlexander von Gluck IV int hash1 = hash(vnid), hash2 = hash(loc);
2109f3ba01bSAlexander von Gluck IV struct vcache_entry *e, *c, *p;
2119f3ba01bSAlexander von Gluck IV
212*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "/%" B_PRIdINO "\n", vnid, loc);
2139f3ba01bSAlexander von Gluck IV
2149f3ba01bSAlexander von Gluck IV e = (vcache_entry*)malloc(sizeof(struct vcache_entry));
2159f3ba01bSAlexander von Gluck IV if (e == NULL)
2169f3ba01bSAlexander von Gluck IV return ENOMEM;
2179f3ba01bSAlexander von Gluck IV
218*342a1b22SJim906 e->vnid = vnid; e->loc = loc; e->constructed = false; e->next_vnid = NULL; e->next_loc = NULL;
2199f3ba01bSAlexander von Gluck IV
2209f3ba01bSAlexander von Gluck IV c = p = vol->vcache.by_vnid[hash1];
2219f3ba01bSAlexander von Gluck IV while (c) {
2229f3ba01bSAlexander von Gluck IV if (vnid < c->vnid)
2239f3ba01bSAlexander von Gluck IV break;
2249f3ba01bSAlexander von Gluck IV ASSERT(vnid != c->vnid); ASSERT(loc != c->loc);
2259f3ba01bSAlexander von Gluck IV p = c;
2269f3ba01bSAlexander von Gluck IV c = c->next_vnid;
2279f3ba01bSAlexander von Gluck IV }
2289f3ba01bSAlexander von Gluck IV ASSERT(!c || (vnid != c->vnid));
2299f3ba01bSAlexander von Gluck IV
2309f3ba01bSAlexander von Gluck IV e->next_vnid = c;
2319f3ba01bSAlexander von Gluck IV if (p == c)
2329f3ba01bSAlexander von Gluck IV vol->vcache.by_vnid[hash1] = e;
2339f3ba01bSAlexander von Gluck IV else
2349f3ba01bSAlexander von Gluck IV p->next_vnid = e;
2359f3ba01bSAlexander von Gluck IV
2369f3ba01bSAlexander von Gluck IV c = p = vol->vcache.by_loc[hash2];
2379f3ba01bSAlexander von Gluck IV while (c) {
2389f3ba01bSAlexander von Gluck IV if (loc < c->loc)
2399f3ba01bSAlexander von Gluck IV break;
2409f3ba01bSAlexander von Gluck IV ASSERT(vnid != c->vnid); ASSERT(loc != c->loc);
2419f3ba01bSAlexander von Gluck IV p = c;
2429f3ba01bSAlexander von Gluck IV c = c->next_loc;
2439f3ba01bSAlexander von Gluck IV }
2449f3ba01bSAlexander von Gluck IV ASSERT(!c || (loc != c->loc));
2459f3ba01bSAlexander von Gluck IV
2469f3ba01bSAlexander von Gluck IV e->next_loc = c;
2479f3ba01bSAlexander von Gluck IV if (p == c)
2489f3ba01bSAlexander von Gluck IV vol->vcache.by_loc[hash2] = e;
2499f3ba01bSAlexander von Gluck IV else
2509f3ba01bSAlexander von Gluck IV p->next_loc = e;
2519f3ba01bSAlexander von Gluck IV
2529f3ba01bSAlexander von Gluck IV return B_OK;
2539f3ba01bSAlexander von Gluck IV }
2549f3ba01bSAlexander von Gluck IV
2559f3ba01bSAlexander von Gluck IV
2569f3ba01bSAlexander von Gluck IV static status_t
_remove_from_vcache_(mount * vol,ino_t vnid)257*342a1b22SJim906 _remove_from_vcache_(mount* vol, ino_t vnid)
2589f3ba01bSAlexander von Gluck IV {
2599f3ba01bSAlexander von Gluck IV int hash1 = hash(vnid), hash2;
2609f3ba01bSAlexander von Gluck IV struct vcache_entry *c, *p, *e;
2619f3ba01bSAlexander von Gluck IV
262*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "\n", vnid);
2639f3ba01bSAlexander von Gluck IV
2649f3ba01bSAlexander von Gluck IV c = p = vol->vcache.by_vnid[hash1];
2659f3ba01bSAlexander von Gluck IV while (c) {
2669f3ba01bSAlexander von Gluck IV if (vnid == c->vnid)
2679f3ba01bSAlexander von Gluck IV break;
2689f3ba01bSAlexander von Gluck IV ASSERT(c->vnid < vnid);
2699f3ba01bSAlexander von Gluck IV p = c;
2709f3ba01bSAlexander von Gluck IV c = c->next_vnid;
2719f3ba01bSAlexander von Gluck IV }
2729f3ba01bSAlexander von Gluck IV ASSERT(c);
2739f3ba01bSAlexander von Gluck IV if (!c) return ENOENT;
2749f3ba01bSAlexander von Gluck IV
2759f3ba01bSAlexander von Gluck IV if (p == c)
2769f3ba01bSAlexander von Gluck IV vol->vcache.by_vnid[hash1] = c->next_vnid;
2779f3ba01bSAlexander von Gluck IV else
2789f3ba01bSAlexander von Gluck IV p->next_vnid = c->next_vnid;
2799f3ba01bSAlexander von Gluck IV
2809f3ba01bSAlexander von Gluck IV e = c;
2819f3ba01bSAlexander von Gluck IV
2829f3ba01bSAlexander von Gluck IV hash2 = hash(c->loc);
2839f3ba01bSAlexander von Gluck IV c = p = vol->vcache.by_loc[hash2];
2849f3ba01bSAlexander von Gluck IV
2859f3ba01bSAlexander von Gluck IV while (c) {
2869f3ba01bSAlexander von Gluck IV if (vnid == c->vnid)
2879f3ba01bSAlexander von Gluck IV break;
2889f3ba01bSAlexander von Gluck IV ASSERT(c->loc < e->loc);
2899f3ba01bSAlexander von Gluck IV p = c;
2909f3ba01bSAlexander von Gluck IV c = c->next_loc;
2919f3ba01bSAlexander von Gluck IV }
2929f3ba01bSAlexander von Gluck IV ASSERT(c);
2939f3ba01bSAlexander von Gluck IV if (!c) return ENOENT;
2949f3ba01bSAlexander von Gluck IV if (p == c)
2959f3ba01bSAlexander von Gluck IV vol->vcache.by_loc[hash2] = c->next_loc;
2969f3ba01bSAlexander von Gluck IV else
2979f3ba01bSAlexander von Gluck IV p->next_loc = c->next_loc;
2989f3ba01bSAlexander von Gluck IV
2999f3ba01bSAlexander von Gluck IV free(c);
3009f3ba01bSAlexander von Gluck IV
3019f3ba01bSAlexander von Gluck IV return 0;
3029f3ba01bSAlexander von Gluck IV }
3039f3ba01bSAlexander von Gluck IV
3049f3ba01bSAlexander von Gluck IV
3059f3ba01bSAlexander von Gluck IV static struct vcache_entry *
_find_vnid_in_vcache_(mount * vol,ino_t vnid)306*342a1b22SJim906 _find_vnid_in_vcache_(mount* vol, ino_t vnid)
3079f3ba01bSAlexander von Gluck IV {
3089f3ba01bSAlexander von Gluck IV int hash1 = hash(vnid);
3099f3ba01bSAlexander von Gluck IV struct vcache_entry *c;
3109f3ba01bSAlexander von Gluck IV c = vol->vcache.by_vnid[hash1];
3119f3ba01bSAlexander von Gluck IV while (c) {
3129f3ba01bSAlexander von Gluck IV if (c->vnid == vnid)
3139f3ba01bSAlexander von Gluck IV break;
3149f3ba01bSAlexander von Gluck IV if (c->vnid > vnid)
3159f3ba01bSAlexander von Gluck IV return NULL;
3169f3ba01bSAlexander von Gluck IV c = c->next_vnid;
3179f3ba01bSAlexander von Gluck IV }
3189f3ba01bSAlexander von Gluck IV
3199f3ba01bSAlexander von Gluck IV return c;
3209f3ba01bSAlexander von Gluck IV }
3219f3ba01bSAlexander von Gluck IV
3229f3ba01bSAlexander von Gluck IV
3239f3ba01bSAlexander von Gluck IV static struct vcache_entry *
_find_loc_in_vcache_(mount * vol,ino_t loc)324*342a1b22SJim906 _find_loc_in_vcache_(mount* vol, ino_t loc)
3259f3ba01bSAlexander von Gluck IV {
3269f3ba01bSAlexander von Gluck IV int hash2 = hash(loc);
3279f3ba01bSAlexander von Gluck IV struct vcache_entry *c;
3289f3ba01bSAlexander von Gluck IV c = vol->vcache.by_loc[hash2];
3299f3ba01bSAlexander von Gluck IV while (c) {
3309f3ba01bSAlexander von Gluck IV if (c->loc == loc)
3319f3ba01bSAlexander von Gluck IV break;
3329f3ba01bSAlexander von Gluck IV if (c->loc > loc)
3339f3ba01bSAlexander von Gluck IV return NULL;
3349f3ba01bSAlexander von Gluck IV c = c->next_loc;
3359f3ba01bSAlexander von Gluck IV }
3369f3ba01bSAlexander von Gluck IV
3379f3ba01bSAlexander von Gluck IV return c;
3389f3ba01bSAlexander von Gluck IV }
3399f3ba01bSAlexander von Gluck IV
3409f3ba01bSAlexander von Gluck IV
3419f3ba01bSAlexander von Gluck IV status_t
add_to_vcache(mount * vol,ino_t vnid,ino_t loc)342*342a1b22SJim906 add_to_vcache(mount* vol, ino_t vnid, ino_t loc)
3439f3ba01bSAlexander von Gluck IV {
3449f3ba01bSAlexander von Gluck IV status_t result;
3459f3ba01bSAlexander von Gluck IV
3469f3ba01bSAlexander von Gluck IV LOCK_CACHE_W;
3479f3ba01bSAlexander von Gluck IV result = _add_to_vcache_(vol,vnid,loc);
3489f3ba01bSAlexander von Gluck IV UNLOCK_CACHE_W;
3499f3ba01bSAlexander von Gluck IV
350*342a1b22SJim906 if (result < 0) INFORM("add_to_vcache failed (%s)\n", strerror(result));
3519f3ba01bSAlexander von Gluck IV return result;
3529f3ba01bSAlexander von Gluck IV }
3539f3ba01bSAlexander von Gluck IV
3549f3ba01bSAlexander von Gluck IV
3559f3ba01bSAlexander von Gluck IV static status_t
_update_loc_in_vcache_(mount * vol,ino_t vnid,ino_t loc)356*342a1b22SJim906 _update_loc_in_vcache_(mount* vol, ino_t vnid, ino_t loc)
3579f3ba01bSAlexander von Gluck IV {
3589f3ba01bSAlexander von Gluck IV status_t result;
359*342a1b22SJim906 bool constructed;
360*342a1b22SJim906 result = vcache_get_constructed(vol, vnid, &constructed);
361*342a1b22SJim906 if (result != B_OK)
362*342a1b22SJim906 return result;
363*342a1b22SJim906 #if DEBUG
364*342a1b22SJim906 struct vnode *node;
365*342a1b22SJim906 result = vcache_get_node(vol, vnid, &node);
366*342a1b22SJim906 if (result != B_OK)
367*342a1b22SJim906 return result;
368*342a1b22SJim906 #endif // DEBUG
3699f3ba01bSAlexander von Gluck IV
3709f3ba01bSAlexander von Gluck IV result = _remove_from_vcache_(vol, vnid);
371*342a1b22SJim906 if (result == 0) {
3729f3ba01bSAlexander von Gluck IV result = _add_to_vcache_(vol, vnid, loc);
373*342a1b22SJim906 if (result == B_OK && constructed == true)
374*342a1b22SJim906 result = vcache_set_constructed(vol, vnid);
375*342a1b22SJim906 #if DEBUG
376*342a1b22SJim906 if (result == B_OK)
377*342a1b22SJim906 result = vcache_set_node(vol, vnid, node);
378*342a1b22SJim906 #endif // DEBUG
379*342a1b22SJim906 }
3809f3ba01bSAlexander von Gluck IV
3819f3ba01bSAlexander von Gluck IV return result;
3829f3ba01bSAlexander von Gluck IV }
3839f3ba01bSAlexander von Gluck IV
3849f3ba01bSAlexander von Gluck IV
3859f3ba01bSAlexander von Gluck IV status_t
remove_from_vcache(mount * vol,ino_t vnid)386*342a1b22SJim906 remove_from_vcache(mount* vol, ino_t vnid)
3879f3ba01bSAlexander von Gluck IV {
3889f3ba01bSAlexander von Gluck IV status_t result;
3899f3ba01bSAlexander von Gluck IV
3909f3ba01bSAlexander von Gluck IV LOCK_CACHE_W;
3919f3ba01bSAlexander von Gluck IV result = _remove_from_vcache_(vol, vnid);
3929f3ba01bSAlexander von Gluck IV UNLOCK_CACHE_W;
3939f3ba01bSAlexander von Gluck IV
394*342a1b22SJim906 if (result < 0) INFORM("remove_from_vcache failed (%s)\n", strerror(result));
3959f3ba01bSAlexander von Gluck IV return result;
3969f3ba01bSAlexander von Gluck IV }
3979f3ba01bSAlexander von Gluck IV
3989f3ba01bSAlexander von Gluck IV
3999f3ba01bSAlexander von Gluck IV status_t
vcache_vnid_to_loc(mount * vol,ino_t vnid,ino_t * loc)400*342a1b22SJim906 vcache_vnid_to_loc(mount* vol, ino_t vnid, ino_t* loc)
4019f3ba01bSAlexander von Gluck IV {
4029f3ba01bSAlexander von Gluck IV struct vcache_entry *e;
4039f3ba01bSAlexander von Gluck IV
404*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO " %p\n", vnid, loc);
4059f3ba01bSAlexander von Gluck IV
4069f3ba01bSAlexander von Gluck IV LOCK_CACHE_R;
4079f3ba01bSAlexander von Gluck IV e = _find_vnid_in_vcache_(vol, vnid);
4089f3ba01bSAlexander von Gluck IV if (loc && e)
4099f3ba01bSAlexander von Gluck IV *loc = e->loc;
4109f3ba01bSAlexander von Gluck IV UNLOCK_CACHE_R;
4119f3ba01bSAlexander von Gluck IV
4129f3ba01bSAlexander von Gluck IV return (e) ? B_OK : ENOENT;
4139f3ba01bSAlexander von Gluck IV }
4149f3ba01bSAlexander von Gluck IV
4159f3ba01bSAlexander von Gluck IV
4169f3ba01bSAlexander von Gluck IV status_t
vcache_loc_to_vnid(mount * vol,ino_t loc,ino_t * vnid)417*342a1b22SJim906 vcache_loc_to_vnid(mount* vol, ino_t loc, ino_t* vnid)
4189f3ba01bSAlexander von Gluck IV {
4199f3ba01bSAlexander von Gluck IV struct vcache_entry *e;
4209f3ba01bSAlexander von Gluck IV
421*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO " %p\n", loc, vnid);
4229f3ba01bSAlexander von Gluck IV
4239f3ba01bSAlexander von Gluck IV LOCK_CACHE_R;
4249f3ba01bSAlexander von Gluck IV e = _find_loc_in_vcache_(vol, loc);
4259f3ba01bSAlexander von Gluck IV if (vnid && e)
4269f3ba01bSAlexander von Gluck IV *vnid = e->vnid;
4279f3ba01bSAlexander von Gluck IV UNLOCK_CACHE_R;
4289f3ba01bSAlexander von Gluck IV
4299f3ba01bSAlexander von Gluck IV return (e) ? B_OK : ENOENT;
4309f3ba01bSAlexander von Gluck IV }
4319f3ba01bSAlexander von Gluck IV
4329f3ba01bSAlexander von Gluck IV
4339f3ba01bSAlexander von Gluck IV status_t
vcache_set_entry(mount * vol,ino_t vnid,ino_t loc)434*342a1b22SJim906 vcache_set_entry(mount* vol, ino_t vnid, ino_t loc)
4359f3ba01bSAlexander von Gluck IV {
4369f3ba01bSAlexander von Gluck IV struct vcache_entry *e;
4379f3ba01bSAlexander von Gluck IV status_t result = B_OK;
4389f3ba01bSAlexander von Gluck IV
439*342a1b22SJim906 FUNCTION_START("vcache_set_entry: %" B_PRIdINO " -> %" B_PRIdINO "\n", vnid, loc);
4409f3ba01bSAlexander von Gluck IV
4419f3ba01bSAlexander von Gluck IV LOCK_CACHE_W;
4429f3ba01bSAlexander von Gluck IV
4439f3ba01bSAlexander von Gluck IV e = _find_vnid_in_vcache_(vol, vnid);
4449f3ba01bSAlexander von Gluck IV
445*342a1b22SJim906 if (e)
4469f3ba01bSAlexander von Gluck IV result = _update_loc_in_vcache_(vol, vnid, loc);
447*342a1b22SJim906 else
4489f3ba01bSAlexander von Gluck IV result = _add_to_vcache_(vol,vnid,loc);
4499f3ba01bSAlexander von Gluck IV
4509f3ba01bSAlexander von Gluck IV UNLOCK_CACHE_W;
4519f3ba01bSAlexander von Gluck IV
4529f3ba01bSAlexander von Gluck IV return result;
4539f3ba01bSAlexander von Gluck IV }
4549f3ba01bSAlexander von Gluck IV
455*342a1b22SJim906
456*342a1b22SJim906 status_t
vcache_set_constructed(mount * vol,ino_t vnid,bool constructed)457*342a1b22SJim906 vcache_set_constructed(mount* vol, ino_t vnid, bool constructed)
458*342a1b22SJim906 {
459*342a1b22SJim906 struct vcache_entry* cEntry;
460*342a1b22SJim906 status_t result = B_OK;
461*342a1b22SJim906
462*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "\n", vnid);
463*342a1b22SJim906
464*342a1b22SJim906 LOCK_CACHE_W;
465*342a1b22SJim906
466*342a1b22SJim906 cEntry = _find_vnid_in_vcache_(vol, vnid);
467*342a1b22SJim906
468*342a1b22SJim906 if (cEntry != NULL)
469*342a1b22SJim906 cEntry->constructed = constructed;
470*342a1b22SJim906 else
471*342a1b22SJim906 result = B_BAD_VALUE;
472*342a1b22SJim906
473*342a1b22SJim906 UNLOCK_CACHE_W;
474*342a1b22SJim906
475*342a1b22SJim906 return result;
476*342a1b22SJim906 }
477*342a1b22SJim906
478*342a1b22SJim906
479*342a1b22SJim906 status_t
vcache_get_constructed(mount * vol,ino_t vnid,bool * constructed)480*342a1b22SJim906 vcache_get_constructed(mount* vol, ino_t vnid, bool* constructed)
481*342a1b22SJim906 {
482*342a1b22SJim906 struct vcache_entry* cEntry;
483*342a1b22SJim906 status_t result = B_OK;
484*342a1b22SJim906
485*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "\n", vnid);
486*342a1b22SJim906
487*342a1b22SJim906 LOCK_CACHE_W;
488*342a1b22SJim906
489*342a1b22SJim906 cEntry = _find_vnid_in_vcache_(vol, vnid);
490*342a1b22SJim906
491*342a1b22SJim906 if (cEntry != NULL)
492*342a1b22SJim906 *constructed = cEntry->constructed;
493*342a1b22SJim906 else
494*342a1b22SJim906 result = B_BAD_VALUE;
495*342a1b22SJim906
496*342a1b22SJim906 UNLOCK_CACHE_W;
497*342a1b22SJim906
498*342a1b22SJim906 return result;
499*342a1b22SJim906 }
500*342a1b22SJim906
501*342a1b22SJim906
502*342a1b22SJim906 status_t
sync_all_files(mount * vol)503*342a1b22SJim906 sync_all_files(mount* vol)
504*342a1b22SJim906 {
505*342a1b22SJim906 uint32 count = 0, errors = 0;
506*342a1b22SJim906 vnode* bsdNode = NULL;
507*342a1b22SJim906 status_t status = B_OK;
508*342a1b22SJim906
509*342a1b22SJim906 FUNCTION_START("volume @ %p\n", vol);
510*342a1b22SJim906
511*342a1b22SJim906 LOCK_CACHE_R;
512*342a1b22SJim906
513*342a1b22SJim906 for (uint32 i = 0; i < vol->vcache.cache_size; i++) {
514*342a1b22SJim906 for (vcache_entry* cEntry = vol->vcache.by_vnid[i]; cEntry != NULL ;
515*342a1b22SJim906 cEntry = cEntry->next_vnid) {
516*342a1b22SJim906 if (cEntry->constructed == true) {
517*342a1b22SJim906 status = get_vnode(vol->mnt_fsvolume, cEntry->vnid,
518*342a1b22SJim906 reinterpret_cast<void**>(&bsdNode));
519*342a1b22SJim906 if (status != B_OK) {
520*342a1b22SJim906 INFORM("get_vnode: %s\n", strerror(status));
521*342a1b22SJim906 errors++;
522*342a1b22SJim906 } else {
523*342a1b22SJim906 if (bsdNode->v_type == VREG) {
524*342a1b22SJim906 status = file_cache_sync(bsdNode->v_cache);
525*342a1b22SJim906 if (status != B_OK)
526*342a1b22SJim906 errors++;
527*342a1b22SJim906 else
528*342a1b22SJim906 count++;
529*342a1b22SJim906 }
530*342a1b22SJim906 put_vnode(vol->mnt_fsvolume, cEntry->vnid);
531*342a1b22SJim906 }
532*342a1b22SJim906 }
533*342a1b22SJim906 }
534*342a1b22SJim906 }
535*342a1b22SJim906
536*342a1b22SJim906 UNLOCK_CACHE_R;
537*342a1b22SJim906
538*342a1b22SJim906 PRINT("sync'd %" B_PRIu32 " files with %" B_PRIu32 " errors\n", count, errors);
539*342a1b22SJim906
540*342a1b22SJim906 return (errors == 0) ? B_OK : B_ERROR;
541*342a1b22SJim906 }
542*342a1b22SJim906
543*342a1b22SJim906
5449f3ba01bSAlexander von Gluck IV #if DEBUG
545*342a1b22SJim906 status_t
vcache_set_node(mount * vol,ino_t vnid,struct vnode * node)546*342a1b22SJim906 vcache_set_node(mount* vol, ino_t vnid, struct vnode* node)
547*342a1b22SJim906 {
548*342a1b22SJim906 vcache_entry* cEntry;
549*342a1b22SJim906 status_t result = B_OK;
550*342a1b22SJim906
551*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "\n", vnid);
552*342a1b22SJim906
553*342a1b22SJim906 LOCK_CACHE_W;
554*342a1b22SJim906
555*342a1b22SJim906 cEntry = _find_vnid_in_vcache_(vol, vnid);
556*342a1b22SJim906
557*342a1b22SJim906 if (cEntry != NULL)
558*342a1b22SJim906 cEntry->node = node;
559*342a1b22SJim906 else
560*342a1b22SJim906 result = B_BAD_VALUE;
561*342a1b22SJim906
562*342a1b22SJim906 UNLOCK_CACHE_W;
563*342a1b22SJim906
564*342a1b22SJim906 return result;
565*342a1b22SJim906 }
566*342a1b22SJim906
567*342a1b22SJim906
568*342a1b22SJim906 status_t
vcache_get_node(mount * vol,ino_t vnid,struct vnode ** node)569*342a1b22SJim906 vcache_get_node(mount* vol, ino_t vnid, struct vnode** node)
570*342a1b22SJim906 {
571*342a1b22SJim906 vcache_entry* cEntry;
572*342a1b22SJim906 status_t result = B_OK;
573*342a1b22SJim906
574*342a1b22SJim906 FUNCTION_START("%" B_PRIdINO "\n", vnid);
575*342a1b22SJim906
576*342a1b22SJim906 LOCK_CACHE_W;
577*342a1b22SJim906
578*342a1b22SJim906 cEntry = _find_vnid_in_vcache_(vol, vnid);
579*342a1b22SJim906
580*342a1b22SJim906 if (cEntry != NULL)
581*342a1b22SJim906 *node = cEntry->node;
582*342a1b22SJim906 else
583*342a1b22SJim906 result = B_BAD_VALUE;
584*342a1b22SJim906
585*342a1b22SJim906 UNLOCK_CACHE_W;
586*342a1b22SJim906
587*342a1b22SJim906 return result;
588*342a1b22SJim906 }
589*342a1b22SJim906
5909f3ba01bSAlexander von Gluck IV
5919f3ba01bSAlexander von Gluck IV int
debug_dfvnid(int argc,char ** argv)5929f3ba01bSAlexander von Gluck IV debug_dfvnid(int argc, char **argv)
5939f3ba01bSAlexander von Gluck IV {
5949f3ba01bSAlexander von Gluck IV int i;
595*342a1b22SJim906 mount* vol;
5969f3ba01bSAlexander von Gluck IV
5979f3ba01bSAlexander von Gluck IV if (argc < 3) {
598*342a1b22SJim906 kprintf("dfvnid volume vnid\n");
5999f3ba01bSAlexander von Gluck IV return B_OK;
6009f3ba01bSAlexander von Gluck IV }
6019f3ba01bSAlexander von Gluck IV
602*342a1b22SJim906 vol = reinterpret_cast<mount*>(strtoul(argv[1], NULL, 0));
6039f3ba01bSAlexander von Gluck IV if (vol == NULL)
6049f3ba01bSAlexander von Gluck IV return B_OK;
6059f3ba01bSAlexander von Gluck IV
6069f3ba01bSAlexander von Gluck IV for (i = 2; i < argc; i++) {
6079f3ba01bSAlexander von Gluck IV ino_t vnid = strtoull(argv[i], NULL, 0);
6089f3ba01bSAlexander von Gluck IV struct vcache_entry *e;
6099f3ba01bSAlexander von Gluck IV if ((e = _find_vnid_in_vcache_(vol, vnid)) != NULL) {
6109f3ba01bSAlexander von Gluck IV kprintf("vnid %" B_PRIdINO " -> loc %" B_PRIdINO " @ %p\n", vnid,
6119f3ba01bSAlexander von Gluck IV e->loc, e);
6129f3ba01bSAlexander von Gluck IV } else {
6139f3ba01bSAlexander von Gluck IV kprintf("vnid %" B_PRIdINO " not found in vnid cache\n", vnid);
6149f3ba01bSAlexander von Gluck IV }
6159f3ba01bSAlexander von Gluck IV }
6169f3ba01bSAlexander von Gluck IV
6179f3ba01bSAlexander von Gluck IV return B_OK;
6189f3ba01bSAlexander von Gluck IV }
6199f3ba01bSAlexander von Gluck IV
6209f3ba01bSAlexander von Gluck IV
6219f3ba01bSAlexander von Gluck IV int
debug_dfloc(int argc,char ** argv)6229f3ba01bSAlexander von Gluck IV debug_dfloc(int argc, char **argv)
6239f3ba01bSAlexander von Gluck IV {
6249f3ba01bSAlexander von Gluck IV int i;
625*342a1b22SJim906 mount* vol;
6269f3ba01bSAlexander von Gluck IV
6279f3ba01bSAlexander von Gluck IV if (argc < 3) {
628*342a1b22SJim906 kprintf("dfloc volume vnid\n");
6299f3ba01bSAlexander von Gluck IV return B_OK;
6309f3ba01bSAlexander von Gluck IV }
6319f3ba01bSAlexander von Gluck IV
632*342a1b22SJim906 vol = reinterpret_cast<mount*>(strtoul(argv[1], NULL, 0));
6339f3ba01bSAlexander von Gluck IV if (vol == NULL)
6349f3ba01bSAlexander von Gluck IV return B_OK;
6359f3ba01bSAlexander von Gluck IV
6369f3ba01bSAlexander von Gluck IV for (i = 2; i < argc; i++) {
6379f3ba01bSAlexander von Gluck IV ino_t loc = strtoull(argv[i], NULL, 0);
6389f3ba01bSAlexander von Gluck IV struct vcache_entry *e;
6399f3ba01bSAlexander von Gluck IV if ((e = _find_loc_in_vcache_(vol, loc)) != NULL) {
6409f3ba01bSAlexander von Gluck IV kprintf("loc %" B_PRIdINO " -> vnid %" B_PRIdINO " @ %p\n", loc,
6419f3ba01bSAlexander von Gluck IV e->vnid, e);
6429f3ba01bSAlexander von Gluck IV } else {
6439f3ba01bSAlexander von Gluck IV kprintf("loc %" B_PRIdINO " not found in vnid cache\n", loc);
6449f3ba01bSAlexander von Gluck IV }
6459f3ba01bSAlexander von Gluck IV }
6469f3ba01bSAlexander von Gluck IV
6479f3ba01bSAlexander von Gluck IV return B_OK;
6489f3ba01bSAlexander von Gluck IV }
649*342a1b22SJim906 #endif // DEBUG
650