Skip to content

Commit 9fb696a

Browse files
Chi Zhilingnamjaejeon
authored andcommitted
exfat: return the start of next cache in exfat_cache_lookup
Change exfat_cache_lookup to return the cluster number of the last cluster before the next cache (i.e., the end of the current cache range) or the given 'end' if there is no next cache. This allows the caller to know whether the next cluster after the current cache is cached. The function signature is changed to accept an 'end' parameter, which is the upper bound of the search range. The function now stops early if it finds a cache that starts within the current cache's tail, meaning caches are contiguous. The return value is the cluster number at which the next cache starts (minus one) or the original 'end' if no next cache is found. The new behavior is illustrated as follows: cache: [ccccccc-------ccccccccc] search: [..................] return: ^ Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn> Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent 8c6bdce commit 9fb696a

1 file changed

Lines changed: 37 additions & 12 deletions

File tree

fs/exfat/cache.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,41 +80,66 @@ static inline void exfat_cache_update_lru(struct inode *inode,
8080
list_move(&cache->cache_list, &ei->cache_lru);
8181
}
8282

83-
static unsigned int exfat_cache_lookup(struct inode *inode,
84-
unsigned int fclus, struct exfat_cache_id *cid,
83+
/*
84+
* Find the cache that covers or precedes 'fclus' and return the last
85+
* cluster before the next cache range.
86+
*/
87+
static inline unsigned int
88+
exfat_cache_lookup(struct inode *inode, struct exfat_cache_id *cid,
89+
unsigned int fclus, unsigned int end,
8590
unsigned int *cached_fclus, unsigned int *cached_dclus)
8691
{
8792
struct exfat_inode_info *ei = EXFAT_I(inode);
8893
static struct exfat_cache nohit = { .fcluster = 0, };
8994
struct exfat_cache *hit = &nohit, *p;
90-
unsigned int offset = EXFAT_EOF_CLUSTER;
95+
unsigned int tail = 0; /* End boundary of hit cache */
9196

97+
/*
98+
* Search range [fclus, end]. Stop early if:
99+
* 1. Cache covers entire range, or
100+
* 2. Next cache starts at current cache tail
101+
*/
92102
spin_lock(&ei->cache_lru_lock);
93103
list_for_each_entry(p, &ei->cache_lru, cache_list) {
94104
/* Find the cache of "fclus" or nearest cache. */
95-
if (p->fcluster <= fclus && hit->fcluster <= p->fcluster) {
105+
if (p->fcluster <= fclus) {
106+
if (p->fcluster < hit->fcluster)
107+
continue;
108+
96109
hit = p;
97-
if (hit->fcluster + hit->nr_contig < fclus) {
98-
offset = hit->nr_contig;
99-
} else {
100-
offset = fclus - hit->fcluster;
110+
tail = hit->fcluster + hit->nr_contig;
111+
112+
/* Current cache covers [fclus, end] completely */
113+
if (tail >= end)
114+
break;
115+
} else if (p->fcluster <= end) {
116+
end = p->fcluster - 1;
117+
118+
/*
119+
* If we have a hit and next cache starts within/at
120+
* its tail, caches are contiguous, stop searching.
121+
*/
122+
if (tail && tail >= end)
101123
break;
102-
}
103124
}
104125
}
105126
if (hit != &nohit) {
106-
exfat_cache_update_lru(inode, hit);
127+
unsigned int offset;
107128

129+
exfat_cache_update_lru(inode, hit);
108130
cid->id = ei->cache_valid_id;
109131
cid->nr_contig = hit->nr_contig;
110132
cid->fcluster = hit->fcluster;
111133
cid->dcluster = hit->dcluster;
134+
135+
offset = min(cid->nr_contig, fclus - cid->fcluster);
112136
*cached_fclus = cid->fcluster + offset;
113137
*cached_dclus = cid->dcluster + offset;
114138
}
115139
spin_unlock(&ei->cache_lru_lock);
116140

117-
return offset;
141+
/* Return next cache start or 'end' if no more caches */
142+
return end;
118143
}
119144

120145
static struct exfat_cache *exfat_cache_merge(struct inode *inode,
@@ -260,7 +285,7 @@ int exfat_get_cluster(struct inode *inode, unsigned int cluster,
260285
return 0;
261286

262287
cache_init(&cid, fclus, *dclus);
263-
exfat_cache_lookup(inode, cluster, &cid, &fclus, dclus);
288+
exfat_cache_lookup(inode, &cid, cluster, cluster, &fclus, dclus);
264289

265290
if (fclus == cluster)
266291
return 0;

0 commit comments

Comments
 (0)