diff --git a/src/add-ons/kernel/file_systems/fat/dir.c b/src/add-ons/kernel/file_systems/fat/dir.c index 4a0b77cb32..4ea3190133 100644 --- a/src/add-ons/kernel/file_systems/fat/dir.c +++ b/src/add-ons/kernel/file_systems/fat/dir.c @@ -532,7 +532,7 @@ compact_directory(nspace *vol, vnode *dir) < dir->st_size) { DPRINTF(0, ("shrinking directory to %" B_PRIu32 " clusters\n", clusters)); - error = set_fat_chain_length(vol, dir, clusters); + error = set_fat_chain_length(vol, dir, clusters, true); dir->st_size = clusters * vol->bytes_per_sector * vol->sectors_per_cluster; dir->iteration++; @@ -698,8 +698,11 @@ _create_dir_entry_(nspace *vol, vnode *dir, struct _entry_info_ *info, DPRINTF(0, ("expanding directory from %" B_PRIdOFF " to %" B_PRIu32 " clusters\n", dir->st_size / vol->bytes_per_sector / vol->sectors_per_cluster, clusters_needed)); - if ((error = set_fat_chain_length(vol, dir, clusters_needed)) < 0) + if ((error = set_fat_chain_length(vol, dir, clusters_needed, false)) + < 0) { return error; + } + dir->st_size = vol->bytes_per_sector*vol->sectors_per_cluster*clusters_needed; dir->iteration++; } diff --git a/src/add-ons/kernel/file_systems/fat/fat.c b/src/add-ons/kernel/file_systems/fat/fat.c index cb48df30a9..6abc26688b 100644 --- a/src/add-ons/kernel/file_systems/fat/fat.c +++ b/src/add-ons/kernel/file_systems/fat/fat.c @@ -331,12 +331,12 @@ bi: DPRINTF(0, ("pooh. there is a problem. clearing chain (%" B_PRIu32 ")\n", first)); if (first != 0) - clear_fat_chain(vol, first); + clear_fat_chain(vol, first, false); } else if (n != N) { DPRINTF(0, ("not enough free entries (%" B_PRId32 "/%" B_PRId32 " found)\n", n, N)); if (first != 0) - clear_fat_chain(vol, first); + clear_fat_chain(vol, first, false); result = B_DEVICE_FULL; } else if (result == 0) { vol->last_allocated = cluster; @@ -447,7 +447,7 @@ count_clusters(nspace *vol, int32 cluster) status_t -clear_fat_chain(nspace *vol, uint32 cluster) +clear_fat_chain(nspace *vol, uint32 cluster, bool discardBlockCache) { int32 c; status_t result; @@ -474,6 +474,12 @@ clear_fat_chain(nspace *vol, uint32 cluster) return result; } + if (discardBlockCache) { + block_cache_discard(vol->fBlockCache, + vol->data_start + (cluster - 2) * vol->sectors_per_cluster, + vol->sectors_per_cluster); + } + vol->free_clusters++; cluster = c; DPRINTF(2, (", %" B_PRIu32, cluster)); @@ -514,7 +520,8 @@ allocate_n_fat_entries(nspace *vol, int32 n, int32 *start) status_t -set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters) +set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters, + bool discardBlockCache) { status_t result; int32 i, c, n; @@ -535,7 +542,7 @@ set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters) return B_OK; c = node->cluster; - if ((result = clear_fat_chain(vol, c)) != B_OK) + if ((result = clear_fat_chain(vol, c, discardBlockCache)) != B_OK) return result; node->cluster = 0; @@ -594,7 +601,7 @@ set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters) result = set_fat_entry(vol, node->end_cluster, n); if (result < B_OK) { - clear_fat_chain(vol, n); + clear_fat_chain(vol, n, false); return result; } @@ -631,7 +638,7 @@ set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters) return result; node->end_cluster = c; - return clear_fat_chain(vol, n); + return clear_fat_chain(vol, n, discardBlockCache); } diff --git a/src/add-ons/kernel/file_systems/fat/fat.h b/src/add-ons/kernel/file_systems/fat/fat.h index 4ffc0d0dbc..edbcb70785 100644 --- a/src/add-ons/kernel/file_systems/fat/fat.h +++ b/src/add-ons/kernel/file_systems/fat/fat.h @@ -20,13 +20,15 @@ int32 get_nth_fat_entry(nspace *vol, int32 cluster, uint32 n); uint32 count_clusters(nspace *vol, int32 cluster); /* remember to update vnode iteration after calling this function */ -status_t clear_fat_chain(nspace *vol, uint32 cluster); +status_t clear_fat_chain(nspace *vol, uint32 cluster, + bool discardBlockCache); /* remember to set end of chain field when merging into a vnode */ status_t allocate_n_fat_entries(nspace *vol, int32 n, int32 *start); /* remember to update vnode iteration after calling this function */ -status_t set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters); +status_t set_fat_chain_length(nspace *vol, vnode *node, uint32 clusters, + bool discardBlockCache); void dump_fat_chain(nspace *vol, uint32 cluster); diff --git a/src/add-ons/kernel/file_systems/fat/file.c b/src/add-ons/kernel/file_systems/fat/file.c index b304e370ca..b15377bdcb 100644 --- a/src/add-ons/kernel/file_systems/fat/file.c +++ b/src/add-ons/kernel/file_systems/fat/file.c @@ -239,7 +239,8 @@ dosfs_wstat(fs_volume *_vol, fs_vnode *_node, const struct stat *st, / vol->sectors_per_cluster; DPRINTF(0, ("setting fat chain length to %" B_PRIu32 " clusters\n", clusters)); - if ((err = set_fat_chain_length(vol, node, clusters)) == B_OK) { + if ((err = set_fat_chain_length(vol, node, clusters, false)) + == B_OK) { node->st_size = st->st_size; node->iteration++; dirty = true; @@ -321,7 +322,7 @@ dosfs_open(fs_volume *_vol, fs_vnode *_node, int omode, void **_cookie) if (omode & O_TRUNC) { DPRINTF(0, ("dosfs_open called with O_TRUNC set\n")); - if ((result = set_fat_chain_length(vol, node, 0)) != B_OK) { + if ((result = set_fat_chain_length(vol, node, 0, false)) != B_OK) { dprintf("dosfs_open: error truncating file\n"); goto error; } @@ -446,7 +447,8 @@ dosfs_write(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos, if (pos + *len > node->st_size) { uint32 clusters = (pos + *len + vol->bytes_per_sector*vol->sectors_per_cluster - 1) / vol->bytes_per_sector / vol->sectors_per_cluster; if (node->st_size <= (clusters - 1) * vol->sectors_per_cluster * vol->bytes_per_sector) { - if ((result = set_fat_chain_length(vol, node, clusters)) != B_OK) { + if ((result = set_fat_chain_length(vol, node, clusters, false)) + != B_OK) { goto bi; } node->iteration++; @@ -588,7 +590,7 @@ dosfs_create(fs_volume *_vol, fs_vnode *_dir, const char *name, int omode, } if (omode & O_TRUNC) { - set_fat_chain_length(vol, file, 0); + set_fat_chain_length(vol, file, 0, false); file->st_size = 0; file->iteration++; } @@ -807,7 +809,7 @@ bi3: if (IS_ARTIFICIAL_VNID(dummy.vnid)) remove_from_vcache(vol, dummy.vnid); bi2: - clear_fat_chain(vol, dummy.cluster); + clear_fat_chain(vol, dummy.cluster, false); if (vol->fs_flags & FS_FLAGS_OP_SYNC) _dosfs_sync(vol); bi: @@ -1064,7 +1066,7 @@ dosfs_remove_vnode(fs_volume *_vol, fs_vnode *_node, bool reenter) /* XXX: the following assertion was tripped */ ASSERT((node->cluster != 0) || (node->st_size == 0)); if (node->cluster != 0) - clear_fat_chain(vol, node->cluster); + clear_fat_chain(vol, node->cluster, (node->mode & FAT_SUBDIR) != 0); /* remove vnode id from the cache */ if (find_vnid_in_vcache(vol, node->vnid) == B_OK)