firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-fs_fat_fatent.c.patch

238 lines
5.9 KiB
Diff

diff -drupN a/fs/fat/fatent.c b/fs/fat/fatent.c
--- a/fs/fat/fatent.c 2018-08-06 17:23:04.000000000 +0300
+++ b/fs/fat/fatent.c 2022-06-12 05:28:14.000000000 +0300
@@ -380,6 +380,9 @@ static int fat_mirror_bhs(struct super_b
int err, n, copy;
err = 0;
+#ifdef CONFIG_FAT1_UPDATE_ONLY
+ return 0;
+#endif
for (copy = 1; copy < sbi->fats; copy++) {
sector_t backup_fat = sbi->fat_length * copy;
@@ -458,6 +461,51 @@ static void fat_collect_bhs(struct buffe
}
}
}
+#ifdef CONFIG_PRELLOCATE_FLAG
+int fat_caculate_cluster(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ const struct fatent_operations *ops = sbi->fatent_ops;
+ struct fat_entry fatent;
+ unsigned int nr_cluster = 0;
+ int err = 0, cluster = 0;
+ fatent_init(&fatent);
+ fatent_set_entry(&fatent, MSDOS_I(inode)->i_start);
+ err = fat_ent_read_block(sb, &fatent);
+ if (err)
+ goto error;
+
+ while (ops->ent_get(&fatent) != FAT_ENT_EOF) {
+ cluster = ops->ent_get(&fatent);
+ if (cluster < 0) {
+ err = cluster;
+ pr_err("FAT ERR: %s: invalid FAT entry value",
+ __func__);
+ goto error;
+ } else if (cluster == FAT_ENT_FREE) {
+ pr_err("FAT ERR: %s: deleting FAT entry beyond EOF",
+ __func__);
+ err = -EIO;
+ goto error;
+ }
+ nr_cluster++;
+ fatent_set_entry(&fatent, cluster);
+ err = fat_ent_read_block(sb, &fatent);
+ if (err)
+ goto error;
+ }
+error:
+ fatent_brelse(&fatent);
+ if (err)
+ return err;
+
+ if (nr_cluster)
+ return nr_cluster + 1;
+ else
+ return 0;
+}
+#endif
int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
{
@@ -468,6 +516,8 @@ int fat_alloc_clusters(struct inode *ino
struct buffer_head *bhs[MAX_BUF_PER_PAGE];
int i, count, err, nr_bhs, idx_clus;
+ if (nr_cluster > (MAX_BUF_PER_PAGE / 2))
+ printk("nr_cluster %d,max nr_cluster %lu\n", nr_cluster, (MAX_BUF_PER_PAGE / 2));
BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */
lock_fat(sbi);
@@ -547,6 +597,57 @@ out:
return err;
}
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM_DISCARD
+int fat_discard_clusters(struct inode *inode, int cluster)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct fat_entry fatent;
+ int err;
+ int first_cl = cluster;
+
+ fatent_init(&fatent);
+ lock_fat(sbi);
+ do {
+ cluster = fat_ent_read(inode, &fatent, cluster);
+ if (cluster < 0) {
+ err = cluster;
+ goto error;
+ } else if (cluster == FAT_ENT_FREE) {
+ fat_fs_error(sb, "%s: deleting FAT entry beyond EOF",
+ __func__);
+ err = -EIO;
+ goto error;
+ }
+
+ if (sbi->options.discard) {
+ /*
+ * Issue discard for the sectors we no longer
+ * care about, batching contiguous clusters
+ * into one request
+ */
+ if (cluster != fatent.entry + 1) {
+ int nr_clus = fatent.entry - first_cl + 1;
+
+ sb_issue_discard(sb,
+ fat_clus_to_blknr(sbi, first_cl),
+ nr_clus * sbi->sec_per_clus,
+ GFP_NOFS, 0);
+
+ first_cl = cluster;
+ }
+ }
+
+ } while (cluster != FAT_ENT_EOF);
+error:
+ fatent_brelse(&fatent);
+ unlock_fat(sbi);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(fat_discard_clusters);
+#endif
+
int fat_free_clusters(struct inode *inode, int cluster)
{
struct super_block *sb = inode->i_sb;
@@ -690,3 +791,104 @@ out:
unlock_fat(sbi);
return err;
}
+
+static int fat_trim_clusters(struct super_block *sb, u32 clus, u32 nr_clus)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ return sb_issue_discard(sb, fat_clus_to_blknr(sbi, clus),
+ nr_clus * sbi->sec_per_clus, GFP_NOFS, 0);
+}
+
+int fat_trim_fs(struct inode *inode, struct fstrim_range *range)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ const struct fatent_operations *ops = sbi->fatent_ops;
+ struct fat_entry fatent;
+ u64 ent_start, ent_end, minlen, trimmed = 0;
+ u32 free = 0;
+ unsigned long reada_blocks, reada_mask, cur_block = 0;
+ int err = 0;
+
+ /*
+ * FAT data is organized as clusters, trim at the granulary of cluster.
+ *
+ * fstrim_range is in byte, convert vaules to cluster index.
+ * Treat sectors before data region as all used, not to trim them.
+ */
+ ent_start = max_t(u64, range->start>>sbi->cluster_bits, FAT_START_ENT);
+ ent_end = ent_start + (range->len >> sbi->cluster_bits) - 1;
+ minlen = range->minlen >> sbi->cluster_bits;
+
+ if (ent_start >= sbi->max_cluster || range->len < sbi->cluster_size)
+ return -EINVAL;
+ if (ent_end >= sbi->max_cluster)
+ ent_end = sbi->max_cluster - 1;
+
+ reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
+ reada_mask = reada_blocks - 1;
+
+ fatent_init(&fatent);
+ lock_fat(sbi);
+ fatent_set_entry(&fatent, ent_start);
+ while (fatent.entry <= ent_end) {
+ /* readahead of fat blocks */
+ if ((cur_block & reada_mask) == 0) {
+ unsigned long rest = sbi->fat_length - cur_block;
+ fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
+ }
+ cur_block++;
+
+ err = fat_ent_read_block(sb, &fatent);
+ if (err)
+ goto error;
+ do {
+ if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
+ free++;
+ } else if (free) {
+ if (free >= minlen) {
+ u32 clus = fatent.entry - free;
+
+ err = fat_trim_clusters(sb, clus, free);
+ if (err && err != -EOPNOTSUPP)
+ goto error;
+ if (!err)
+ trimmed += free;
+ err = 0;
+ }
+ free = 0;
+ }
+ } while (fat_ent_next(sbi, &fatent) && fatent.entry <= ent_end);
+
+ if (fatal_signal_pending(current)) {
+ err = -ERESTARTSYS;
+ goto error;
+ }
+
+ if (need_resched()) {
+ fatent_brelse(&fatent);
+ unlock_fat(sbi);
+ cond_resched();
+ lock_fat(sbi);
+ }
+ }
+ /* handle scenario when tail entries are all free */
+ if (free && free >= minlen) {
+ u32 clus = fatent.entry - free;
+
+ err = fat_trim_clusters(sb, clus, free);
+ if (err && err != -EOPNOTSUPP)
+ goto error;
+ if (!err)
+ trimmed += free;
+ err = 0;
+ }
+
+error:
+ fatent_brelse(&fatent);
+ unlock_fat(sbi);
+
+ range->len = trimmed << sbi->cluster_bits;
+
+ return err;
+}