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

197 lines
5.2 KiB
Diff

diff -drupN a/fs/fat/file.c b/fs/fat/file.c
--- a/fs/fat/file.c 2018-08-06 17:23:04.000000000 +0300
+++ b/fs/fat/file.c 2022-06-12 05:28:14.000000000 +0300
@@ -17,6 +17,10 @@
#include <linux/falloc.h>
#include "fat.h"
+#ifdef CONFIG_PRELLOCATE_FLAG
+static DEFINE_MUTEX (i_mutex);
+#endif
+
static long fat_fallocate(struct file *file, int mode,
loff_t offset, loff_t len);
@@ -121,6 +125,37 @@ static int fat_ioctl_get_volume_id(struc
return put_user(sbi->vol_id, user_attr);
}
+static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
+{
+ struct super_block *sb = inode->i_sb;
+ struct fstrim_range __user *user_range;
+ struct fstrim_range range;
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+
+ user_range = (struct fstrim_range __user *)arg;
+ if (copy_from_user(&range, user_range, sizeof(range)))
+ return -EFAULT;
+
+ range.minlen = max_t(unsigned int, range.minlen,
+ q->limits.discard_granularity);
+
+ err = fat_trim_fs(inode, &range);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(user_range, &range, sizeof(range)))
+ return -EFAULT;
+
+ return 0;
+}
+
long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file_inode(filp);
@@ -133,6 +168,8 @@ long fat_generic_ioctl(struct file *filp
return fat_ioctl_set_attributes(filp, user_attr);
case FAT_IOCTL_GET_VOLUME_ID:
return fat_ioctl_get_volume_id(inode, user_attr);
+ case FITRIM:
+ return fat_ioctl_fitrim(inode, arg);
default:
return -ENOTTY; /* Inappropriate ioctl for device */
}
@@ -168,6 +205,17 @@ int fat_file_fsync(struct file *filp, lo
return res ? res : err;
}
+#ifdef CONFIG_OPTIMIZE_METADATA_REFRESH
+int fat_file_flush(struct file *file, fl_owner_t id)
+{
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+
+ inode->i_sb->s_op->write_inode(inode, NULL);
+
+ return 0;
+}
+#endif
const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
@@ -182,6 +230,9 @@ const struct file_operations fat_file_op
.fsync = fat_file_fsync,
.splice_read = generic_file_splice_read,
.fallocate = fat_fallocate,
+#ifdef CONFIG_OPTIMIZE_METADATA_REFRESH
+ .flush = fat_file_flush,
+#endif
};
static int fat_cont_expand(struct inode *inode, loff_t size)
@@ -246,7 +297,17 @@ static long fat_fallocate(struct file *f
if (!S_ISREG(inode->i_mode))
return -EOPNOTSUPP;
+#ifdef CONFIG_PRELLOCATE_FLAG
+ if (check_prealloc(inode)) {
+ fat_msg(sb, KERN_ERR, "Repeatedly called fat_fallocate");
+ return -EOPNOTSUPP;
+ }
+#endif
+
inode_lock(inode);
+#ifdef CONFIG_PRELLOCATE_FLAG
+ mutex_lock(&i_mutex);
+#endif
if (mode & FALLOC_FL_KEEP_SIZE) {
ondisksize = inode->i_blocks << 9;
if ((offset + len) <= ondisksize)
@@ -271,7 +332,13 @@ static long fat_fallocate(struct file *f
err = fat_cont_expand(inode, (offset + len));
}
+#ifdef CONFIG_PRELLOCATE_FLAG
+ mark_prealloc(inode);
+#endif
error:
+#ifdef CONFIG_PRELLOCATE_FLAG
+ mutex_unlock(&i_mutex);
+#endif
inode_unlock(inode);
return err;
}
@@ -290,14 +357,19 @@ static int fat_free(struct inode *inode,
wait = IS_DIRSYNC(inode);
i_start = free_start = MSDOS_I(inode)->i_start;
i_logstart = MSDOS_I(inode)->i_logstart;
-
/* First, we write the new file size. */
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM
+ if (!skip && (inode->i_nlink == 0 || !check_prealloc(inode))) {
+#else
if (!skip) {
+#endif
MSDOS_I(inode)->i_start = 0;
MSDOS_I(inode)->i_logstart = 0;
}
+
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
inode->i_ctime = inode->i_mtime = current_time(inode);
+
if (wait) {
err = fat_sync_inode(inode);
if (err) {
@@ -309,7 +381,11 @@ static int fat_free(struct inode *inode,
mark_inode_dirty(inode);
/* Write a new EOF, and get the remaining cluster chain for freeing. */
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM
+ if (skip && !check_prealloc(inode)) {
+#else
if (skip) {
+#endif
struct fat_entry fatent;
int ret, fclus, dclus;
@@ -340,8 +416,17 @@ static int fat_free(struct inode *inode,
free_start = ret;
}
- inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM
+ if (check_prealloc(inode) && inode->i_nlink) {
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM_DISCARD
+ fat_discard_clusters(inode, free_start);
+#endif
+ return 0;
+ }
+#endif
+
+ inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
/* Freeing the remained cluster chain */
return fat_free_clusters(inode, free_start);
}
@@ -468,10 +553,22 @@ int fat_setattr(struct dentry *dentry, s
inode_dio_wait(inode);
if (attr->ia_size > inode->i_size) {
+#ifdef CONFIG_TRUNCATE_NOMEM_RECLAIM
+ if (!check_prealloc(inode)) {
+ error = fat_cont_expand(inode, attr->ia_size);
+ if (error || attr->ia_valid == ATTR_SIZE)
+ goto out;
+ attr->ia_valid &= ~ATTR_SIZE;
+ } else {
+ pr_err("FAT ERR: (%s) incorrectly call ftruncate", __func__);
+ return -EOPNOTSUPP;
+ }
+#else
error = fat_cont_expand(inode, attr->ia_size);
if (error || attr->ia_valid == ATTR_SIZE)
goto out;
attr->ia_valid &= ~ATTR_SIZE;
+#endif
}
}