^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/fat/cache.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written 1992,1993 by Werner Almesberger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * of inode number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "fat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* this must be > 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define FAT_MAX_CACHE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct fat_cache {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct list_head cache_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int nr_contig; /* number of contiguous clusters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int fcluster; /* cluster number in the file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int dcluster; /* cluster number on disk. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct fat_cache_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int nr_contig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int fcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int dcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline int fat_max_cache(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return FAT_MAX_CACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct kmem_cache *fat_cache_cachep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void init_once(void *foo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct fat_cache *cache = (struct fat_cache *)foo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) INIT_LIST_HEAD(&cache->cache_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int __init fat_cache_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) fat_cache_cachep = kmem_cache_create("fat_cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) sizeof(struct fat_cache),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) init_once);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (fat_cache_cachep == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void fat_cache_destroy(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) kmem_cache_destroy(fat_cache_cachep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return kmem_cache_alloc(fat_cache_cachep, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static inline void fat_cache_free(struct fat_cache *cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) BUG_ON(!list_empty(&cache->cache_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) kmem_cache_free(fat_cache_cachep, cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline void fat_cache_update_lru(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct fat_cache *cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (MSDOS_I(inode)->cache_lru.next != &cache->cache_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) list_move(&cache->cache_list, &MSDOS_I(inode)->cache_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int fat_cache_lookup(struct inode *inode, int fclus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct fat_cache_id *cid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int *cached_fclus, int *cached_dclus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct fat_cache nohit = { .fcluster = 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct fat_cache *hit = &nohit, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int offset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) spin_lock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* Find the cache of "fclus" or nearest cache. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (p->fcluster <= fclus && hit->fcluster < p->fcluster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) hit = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if ((hit->fcluster + hit->nr_contig) < fclus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) offset = hit->nr_contig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) offset = fclus - hit->fcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (hit != &nohit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) fat_cache_update_lru(inode, hit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) cid->id = MSDOS_I(inode)->cache_valid_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) cid->nr_contig = hit->nr_contig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) cid->fcluster = hit->fcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) cid->dcluster = hit->dcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *cached_fclus = cid->fcluster + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *cached_dclus = cid->dcluster + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct fat_cache *fat_cache_merge(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct fat_cache_id *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct fat_cache *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Find the same part as "new" in cluster-chain. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (p->fcluster == new->fcluster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) BUG_ON(p->dcluster != new->dcluster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (new->nr_contig > p->nr_contig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) p->nr_contig = new->nr_contig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void fat_cache_add(struct inode *inode, struct fat_cache_id *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct fat_cache *cache, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (new->fcluster == -1) /* dummy cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) spin_lock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (new->id != FAT_CACHE_VALID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) new->id != MSDOS_I(inode)->cache_valid_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto out; /* this cache was invalidated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) cache = fat_cache_merge(inode, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (cache == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) MSDOS_I(inode)->nr_caches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tmp = fat_cache_alloc(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) spin_lock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) MSDOS_I(inode)->nr_caches--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) spin_lock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cache = fat_cache_merge(inode, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (cache != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) MSDOS_I(inode)->nr_caches--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fat_cache_free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) goto out_update_lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) cache = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct list_head *p = MSDOS_I(inode)->cache_lru.prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) cache = list_entry(p, struct fat_cache, cache_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) cache->fcluster = new->fcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cache->dcluster = new->dcluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cache->nr_contig = new->nr_contig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) out_update_lru:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) fat_cache_update_lru(inode, cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * fixes itself after a while.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void __fat_cache_inval_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct msdos_inode_info *i = MSDOS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct fat_cache *cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) while (!list_empty(&i->cache_lru)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) cache = list_entry(i->cache_lru.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct fat_cache, cache_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) list_del_init(&cache->cache_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) i->nr_caches--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fat_cache_free(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* Update. The copy of caches before this id is discarded. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) i->cache_valid_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (i->cache_valid_id == FAT_CACHE_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) i->cache_valid_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) void fat_cache_inval_inode(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_lock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) __fat_cache_inval_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static inline int cache_contiguous(struct fat_cache_id *cid, int dclus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) cid->nr_contig++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ((cid->dcluster + cid->nr_contig) == dclus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) cid->id = FAT_CACHE_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) cid->fcluster = fclus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) cid->dcluster = dclus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) cid->nr_contig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct msdos_sb_info *sbi = MSDOS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) const int limit = sb->s_maxbytes >> sbi->cluster_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct fat_entry fatent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct fat_cache_id cid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) BUG_ON(MSDOS_I(inode)->i_start == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *fclus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *dclus = MSDOS_I(inode)->i_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!fat_valid_entry(sbi, *dclus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) fat_fs_error_ratelimit(sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) "%s: invalid start cluster (i_pos %lld, start %08x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) __func__, MSDOS_I(inode)->i_pos, *dclus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (cluster == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (fat_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * dummy, always not contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * This is reinitialized by cache_init(), later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) cache_init(&cid, -1, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fatent_init(&fatent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) while (*fclus < cluster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* prevent the infinite loop of cluster chain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (*fclus > limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) fat_fs_error_ratelimit(sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) "%s: detected the cluster chain loop (i_pos %lld)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) __func__, MSDOS_I(inode)->i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) nr = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) nr = fat_ent_read(inode, &fatent, *dclus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (nr < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) else if (nr == FAT_ENT_FREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fat_fs_error_ratelimit(sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) "%s: invalid cluster chain (i_pos %lld)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) __func__, MSDOS_I(inode)->i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) nr = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } else if (nr == FAT_ENT_EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) fat_cache_add(inode, &cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) (*fclus)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *dclus = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!cache_contiguous(&cid, *dclus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) cache_init(&cid, *fclus, *dclus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) fat_cache_add(inode, &cid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) fatent_brelse(&fatent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int fat_bmap_cluster(struct inode *inode, int cluster)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int ret, fclus, dclus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (MSDOS_I(inode)->i_start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = fat_get_cluster(inode, cluster, &fclus, &dclus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else if (ret == FAT_ENT_EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fat_fs_error(sb, "%s: request beyond EOF (i_pos %lld)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) __func__, MSDOS_I(inode)->i_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return dclus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int fat_get_mapped_cluster(struct inode *inode, sector_t sector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) sector_t last_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned long *mapped_blocks, sector_t *bmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct msdos_sb_info *sbi = MSDOS_SB(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int cluster, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) offset = sector & (sbi->sec_per_clus - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) cluster = fat_bmap_cluster(inode, cluster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (cluster < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return cluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) else if (cluster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *bmap = fat_clus_to_blknr(sbi, cluster) + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *mapped_blocks = sbi->sec_per_clus - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (*mapped_blocks > last_block - sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *mapped_blocks = last_block - sector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int is_exceed_eof(struct inode *inode, sector_t sector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) sector_t *last_block, int create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) const unsigned long blocksize = sb->s_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) const unsigned char blocksize_bits = sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) *last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (sector >= *last_block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * ->mmu_private can access on only allocation path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * (caller must hold ->i_mutex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) >> blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (sector >= *last_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) unsigned long *mapped_blocks, int create, bool from_bmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) sector_t last_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *phys = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *mapped_blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!is_fat32(sbi) && (inode->i_ino == MSDOS_ROOT_INO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *phys = sector + sbi->dir_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) *mapped_blocks = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!from_bmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (is_exceed_eof(inode, sector, &last_block, create))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) last_block = inode->i_blocks >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) (inode->i_sb->s_blocksize_bits - 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (sector >= last_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return fat_get_mapped_cluster(inode, sector, last_block, mapped_blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }