Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }