1.修复exfat卡文件系统问题
This commit is contained in:
parent
17f1537ef9
commit
dc9361e272
|
@ -35,3 +35,4 @@ clean:
|
||||||
|
|
||||||
.PHONY: modules modules_install clean
|
.PHONY: modules modules_install clean
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -66,4 +66,8 @@
|
||||||
#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8"
|
#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef FSLINUX_IOCTL_ENABLE
|
||||||
|
#define FSLINUX_IOCTL_ENABLE 1 /* to speedup by fslinux ioctl */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _EXFAT_CONFIG_H */
|
#endif /* _EXFAT_CONFIG_H */
|
||||||
|
|
|
@ -970,6 +970,9 @@ s32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid)
|
||||||
CHAIN_T dir, clu_to_free;
|
CHAIN_T dir, clu_to_free;
|
||||||
DENTRY_T *ep;
|
DENTRY_T *ep;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
#endif
|
||||||
FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
|
FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
|
||||||
|
|
||||||
dir.dir = fid->dir.dir;
|
dir.dir = fid->dir.dir;
|
||||||
|
@ -994,6 +997,11 @@ s32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid)
|
||||||
clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
|
clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
|
||||||
clu_to_free.flags = fid->flags;
|
clu_to_free.flags = fid->flags;
|
||||||
|
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
if (!EXFAT_IS_DELAY_SYNC(sbi, inode))
|
||||||
|
#endif
|
||||||
|
ffsSyncVol(sb, 1);
|
||||||
|
|
||||||
/* (2) free the clusters */
|
/* (2) free the clusters */
|
||||||
p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
|
p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
|
||||||
|
|
||||||
|
|
|
@ -128,13 +128,13 @@ static time_t accum_days_in_year[] = {
|
||||||
|
|
||||||
TIMESTAMP_T *tm_current(TIMESTAMP_T *tp)
|
TIMESTAMP_T *tm_current(TIMESTAMP_T *tp)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec_compat ts;
|
||||||
time_t second, day, leap_day, month, year;
|
time_t second, day, leap_day, month, year;
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
|
||||||
ts = CURRENT_TIME_SEC;
|
ts = CURRENT_TIME_SEC;
|
||||||
#else
|
#else
|
||||||
ktime_get_real_ts(&ts);
|
KTIME_GET_REAL_TS(&ts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
second = ts.tv_sec;
|
second = ts.tv_sec;
|
||||||
|
|
|
@ -51,6 +51,13 @@
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
|
||||||
|
#define timespec_compat timespec64
|
||||||
|
#define KTIME_GET_REAL_TS ktime_get_real_ts64
|
||||||
|
#else
|
||||||
|
#define timespec_compat timespec
|
||||||
|
#define KTIME_GET_REAL_TS ktime_get_real_ts
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 sec; /* 0 ~ 59 */
|
u16 sec; /* 0 ~ 59 */
|
||||||
|
|
|
@ -63,9 +63,6 @@
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
|
||||||
#include <linux/aio.h>
|
#include <linux/aio.h>
|
||||||
#endif
|
#endif
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
|
||||||
#include <linux/iversion.h>
|
|
||||||
#endif
|
|
||||||
#include <linux/parser.h>
|
#include <linux/parser.h>
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
|
@ -102,17 +99,6 @@ extern struct timezone sys_tz;
|
||||||
#define current_time(x) (CURRENT_TIME_SEC)
|
#define current_time(x) (CURRENT_TIME_SEC)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
|
||||||
#define USE_NEW_IVERSION_API
|
|
||||||
#define INC_IVERSION(x) (inode_inc_iversion(x))
|
|
||||||
#define GET_IVERSION(x) (inode_peek_iversion_raw(x))
|
|
||||||
#define SET_IVERSION(x,y) (inode_set_iversion(x, y))
|
|
||||||
#else
|
|
||||||
#define INC_IVERSION(x) (x->i_version++)
|
|
||||||
#define GET_IVERSION(x) (x->i_version)
|
|
||||||
#define SET_IVERSION(x,y) (x->i_version = y)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CHECK_ERR(x) BUG_ON(x)
|
#define CHECK_ERR(x) BUG_ON(x)
|
||||||
|
|
||||||
#define UNIX_SECS_1980 315532800L
|
#define UNIX_SECS_1980 315532800L
|
||||||
|
@ -147,7 +133,8 @@ static time_t accum_days_in_year[] = {
|
||||||
static void _exfat_truncate(struct inode *inode, loff_t old_size);
|
static void _exfat_truncate(struct inode *inode, loff_t old_size);
|
||||||
|
|
||||||
/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
|
/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
|
||||||
void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec64 *ts,DATE_TIME_T *tp)
|
void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec_compat *ts,
|
||||||
|
DATE_TIME_T *tp)
|
||||||
{
|
{
|
||||||
time_t year = tp->Year;
|
time_t year = tp->Year;
|
||||||
time_t ld;
|
time_t ld;
|
||||||
|
@ -176,7 +163,7 @@ void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec64 *ts,DATE_T
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert linear UNIX date to a FAT time/date pair. */
|
/* Convert linear UNIX date to a FAT time/date pair. */
|
||||||
void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec_compat *ts,
|
||||||
DATE_TIME_T *tp)
|
DATE_TIME_T *tp)
|
||||||
{
|
{
|
||||||
time_t second = ts->tv_sec;
|
time_t second = ts->tv_sec;
|
||||||
|
@ -651,6 +638,126 @@ static int exfat_ioctl_volume_id(struct inode *dir)
|
||||||
return p_fs->vol_id;
|
return p_fs->vol_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
static int exfat_ioctl_set_delay_sync(struct inode *dir, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct super_block *sb = dir->i_sb;
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
|
||||||
|
__lock_super(sb);
|
||||||
|
if (arg) {
|
||||||
|
sbi->delay_sync.is_delay_sync = 1;
|
||||||
|
sbi->delay_sync.dir_inode = dir;
|
||||||
|
} else {
|
||||||
|
sbi->delay_sync.is_delay_sync = 0;
|
||||||
|
sbi->delay_sync.dir_inode = NULL;
|
||||||
|
}
|
||||||
|
__unlock_super(sb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Duplicated from exfat_readdir and modified it for EXFAT_IOCTL_GET_ENTRY_DATA
|
||||||
|
static int exfat_ioctl_readdir(struct file *filp, void *dirent)
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
|
||||||
|
struct inode *inode = file_inode(filp);
|
||||||
|
#else
|
||||||
|
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||||
|
#endif
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
FS_INFO_T *p_fs = &(sbi->fs_info);
|
||||||
|
BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
|
||||||
|
DIR_ENTRY_T de;
|
||||||
|
unsigned long inum;
|
||||||
|
loff_t cpos;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
__lock_super(sb);
|
||||||
|
|
||||||
|
cpos = filp->f_pos;
|
||||||
|
|
||||||
|
/* Fake . and .. for the root directory. */
|
||||||
|
if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) {
|
||||||
|
while (cpos < 2) {
|
||||||
|
if (inode->i_ino == EXFAT_ROOT_INO)
|
||||||
|
inum = EXFAT_ROOT_INO; //root folder
|
||||||
|
else if (cpos == 0)
|
||||||
|
inum = inode->i_ino; //current folder
|
||||||
|
else /* (cpos == 1) */
|
||||||
|
inum = parent_ino(filp->f_path.dentry); //parent folder
|
||||||
|
|
||||||
|
cpos++;
|
||||||
|
filp->f_pos++;
|
||||||
|
}
|
||||||
|
if (cpos == 2)
|
||||||
|
cpos = 0;
|
||||||
|
}
|
||||||
|
if (cpos & (DENTRY_SIZE - 1)) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXFAT_I(inode)->fid.size = i_size_read(inode);
|
||||||
|
EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS;
|
||||||
|
|
||||||
|
err = FsReadDir(inode, &de);
|
||||||
|
if (err) {
|
||||||
|
/* at least we tried to read a sector
|
||||||
|
* move cpos to next sector position (should be aligned)
|
||||||
|
*/
|
||||||
|
if (err == FFS_MEDIAERR) {
|
||||||
|
cpos += 1 << p_bd->sector_size_bits;
|
||||||
|
cpos &= ~((1 << p_bd->sector_size_bits)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = -EIO;
|
||||||
|
goto end_of_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS;
|
||||||
|
|
||||||
|
if (!de.Name[0]) {
|
||||||
|
if (copy_to_user(dirent, &de, sizeof(DIR_ENTRY_T))) {
|
||||||
|
err = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
goto end_of_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) {
|
||||||
|
inum = inode->i_ino;
|
||||||
|
} else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) {
|
||||||
|
inum = parent_ino(filp->f_path.dentry);
|
||||||
|
} else {
|
||||||
|
loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) |
|
||||||
|
((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff);
|
||||||
|
struct inode *tmp = exfat_iget(sb, i_pos);
|
||||||
|
if (tmp) {
|
||||||
|
inum = tmp->i_ino;
|
||||||
|
iput(tmp);
|
||||||
|
} else {
|
||||||
|
inum = iunique(sb, EXFAT_ROOT_INO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(dirent, &de, sizeof(DIR_ENTRY_T))) {
|
||||||
|
err = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
filp->f_pos = cpos;
|
||||||
|
|
||||||
|
end_of_dir:
|
||||||
|
filp->f_pos = cpos;
|
||||||
|
|
||||||
|
out:
|
||||||
|
__unlock_super(sb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
||||||
static int exfat_generic_ioctl(struct inode *inode, struct file *filp,
|
static int exfat_generic_ioctl(struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
|
@ -698,11 +805,26 @@ static long exfat_generic_ioctl(struct file *filp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
|
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
case EXFAT_IOCTL_READDIR_DIRECT: {
|
||||||
|
int ret = -ENOENT;
|
||||||
|
|
||||||
|
inode_lock(inode);
|
||||||
|
if (!IS_DEADDIR(inode))
|
||||||
|
ret = exfat_ioctl_readdir(filp, (void *)arg);
|
||||||
|
inode_unlock(inode);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case EXFAT_IOCTL_SET_DELAY_SYNC:
|
||||||
|
return exfat_ioctl_set_delay_sync(inode, arg);
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
default:
|
default:
|
||||||
return -ENOTTY; /* Inappropriate ioctl for device */
|
return -ENOTTY; /* Inappropriate ioctl for device */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
|
||||||
static int exfat_file_fsync(struct file *filp, struct dentry *dentry,
|
static int exfat_file_fsync(struct file *filp, struct dentry *dentry,
|
||||||
|
@ -725,6 +847,19 @@ static int exfat_file_fsync(struct file *filp, int datasync)
|
||||||
return res ? res : err;
|
return res ? res : err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
|
||||||
|
{
|
||||||
|
struct inode *inode = filp->f_mapping->host;
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
int res, err;
|
||||||
|
|
||||||
|
res = generic_file_fsync(filp, start, end, datasync);
|
||||||
|
err = FsSyncVol(sb, 1);
|
||||||
|
|
||||||
|
return res ? res : err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const struct file_operations exfat_dir_operations = {
|
const struct file_operations exfat_dir_operations = {
|
||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
|
@ -734,6 +869,7 @@ const struct file_operations exfat_dir_operations = {
|
||||||
#else
|
#else
|
||||||
.readdir = exfat_readdir,
|
.readdir = exfat_readdir,
|
||||||
#endif
|
#endif
|
||||||
|
#if 0
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
||||||
.ioctl = exfat_generic_ioctl,
|
.ioctl = exfat_generic_ioctl,
|
||||||
.fsync = exfat_file_fsync,
|
.fsync = exfat_file_fsync,
|
||||||
|
@ -741,6 +877,10 @@ const struct file_operations exfat_dir_operations = {
|
||||||
.unlocked_ioctl = exfat_generic_ioctl,
|
.unlocked_ioctl = exfat_generic_ioctl,
|
||||||
.fsync = generic_file_fsync,
|
.fsync = generic_file_fsync,
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
.unlocked_ioctl = exfat_generic_ioctl,
|
||||||
|
.fsync = exfat_file_fsync,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00)
|
||||||
|
@ -911,6 +1051,9 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
struct super_block *sb = dir->i_sb;
|
struct super_block *sb = dir->i_sb;
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
__lock_super(sb);
|
__lock_super(sb);
|
||||||
|
@ -929,7 +1072,11 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
}
|
}
|
||||||
INC_IVERSION(dir);
|
INC_IVERSION(dir);
|
||||||
dir->i_mtime = dir->i_atime = current_time(dir);
|
dir->i_mtime = dir->i_atime = current_time(dir);
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
if (!EXFAT_IS_DELAY_SYNC(sbi, dir) && IS_DIRSYNC(dir))
|
||||||
|
#else
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
(void) exfat_sync_inode(dir);
|
(void) exfat_sync_inode(dir);
|
||||||
else
|
else
|
||||||
mark_inode_dirty(dir);
|
mark_inode_dirty(dir);
|
||||||
|
@ -1080,6 +1227,9 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
struct super_block *sb = dir->i_sb;
|
struct super_block *sb = dir->i_sb;
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
__lock_super(sb);
|
__lock_super(sb);
|
||||||
|
@ -1104,6 +1254,13 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
}
|
}
|
||||||
INC_IVERSION(dir);
|
INC_IVERSION(dir);
|
||||||
dir->i_mtime = dir->i_atime = current_time(dir);
|
dir->i_mtime = dir->i_atime = current_time(dir);
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
if (EXFAT_IS_DELAY_SYNC(sbi, inode)) {
|
||||||
|
sbi->delay_sync.is_delay_sync = 0;
|
||||||
|
sbi->delay_sync.dir_inode = NULL;
|
||||||
|
(void) exfat_sync_inode(dir);
|
||||||
|
} else
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
(void) exfat_sync_inode(dir);
|
(void) exfat_sync_inode(dir);
|
||||||
else
|
else
|
||||||
|
@ -1187,6 +1344,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||||
if (!new_inode)
|
if (!new_inode)
|
||||||
inc_nlink(new_dir);
|
inc_nlink(new_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
INC_IVERSION(old_dir);
|
INC_IVERSION(old_dir);
|
||||||
old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
|
old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
|
||||||
if (IS_DIRSYNC(old_dir))
|
if (IS_DIRSYNC(old_dir))
|
||||||
|
@ -1479,12 +1637,17 @@ const struct file_operations exfat_file_operations = {
|
||||||
#endif
|
#endif
|
||||||
.mmap = generic_file_mmap,
|
.mmap = generic_file_mmap,
|
||||||
.release = exfat_file_release,
|
.release = exfat_file_release,
|
||||||
|
#if 0
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
||||||
.ioctl = exfat_generic_ioctl,
|
.ioctl = exfat_generic_ioctl,
|
||||||
.fsync = exfat_file_fsync,
|
.fsync = exfat_file_fsync,
|
||||||
#else
|
#else
|
||||||
.unlocked_ioctl = exfat_generic_ioctl,
|
.unlocked_ioctl = exfat_generic_ioctl,
|
||||||
.fsync = generic_file_fsync,
|
.fsync = generic_file_fsync,
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
.unlocked_ioctl = exfat_generic_ioctl,
|
||||||
|
.fsync = exfat_file_fsync,
|
||||||
#endif
|
#endif
|
||||||
.splice_read = generic_file_splice_read,
|
.splice_read = generic_file_splice_read,
|
||||||
};
|
};
|
||||||
|
@ -1724,9 +1887,6 @@ static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
|
||||||
const struct iovec *iov,
|
const struct iovec *iov,
|
||||||
loff_t offset, unsigned long nr_segs)
|
loff_t offset, unsigned long nr_segs)
|
||||||
#endif
|
#endif
|
||||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
|
|
||||||
static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb,
|
|
||||||
struct iov_iter *iter, loff_t offset)
|
|
||||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
|
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
|
||||||
static ssize_t exfat_direct_IO(struct kiocb *iocb,
|
static ssize_t exfat_direct_IO(struct kiocb *iocb,
|
||||||
struct iov_iter *iter, loff_t offset)
|
struct iov_iter *iter, loff_t offset)
|
||||||
|
@ -1739,7 +1899,7 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||||
struct address_space *mapping = iocb->ki_filp->f_mapping;
|
struct address_space *mapping = iocb->ki_filp->f_mapping;
|
||||||
#endif
|
#endif
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
|
||||||
int rw;
|
int rw;
|
||||||
|
|
||||||
rw = iov_iter_rw(iter);
|
rw = iov_iter_rw(iter);
|
||||||
|
@ -1941,8 +2101,6 @@ static int exfat_fill_inode(struct inode *inode, FILE_ID_T *fid)
|
||||||
inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1))
|
inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1))
|
||||||
& ~((loff_t)p_fs->cluster_size - 1)) >> 9;
|
& ~((loff_t)p_fs->cluster_size - 1)) >> 9;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp);
|
exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp);
|
||||||
exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp);
|
exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp);
|
||||||
exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp);
|
exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp);
|
||||||
|
@ -1977,13 +2135,41 @@ out:
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __exfat_write_inode(struct inode *inode, int wait)
|
||||||
|
{
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
DIR_ENTRY_T info;
|
||||||
|
int err = FFS_SUCCESS;
|
||||||
|
|
||||||
|
if (inode->i_ino != EXFAT_ROOT_INO) {
|
||||||
|
info.Attr = exfat_make_attr(inode);
|
||||||
|
info.Size = i_size_read(inode);
|
||||||
|
|
||||||
|
exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp);
|
||||||
|
exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp);
|
||||||
|
exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp);
|
||||||
|
|
||||||
|
FsWriteStat(inode, &info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait)
|
||||||
|
err = FsSyncVol(sb, 1);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int exfat_sync_inode(struct inode *inode)
|
static int exfat_sync_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
|
||||||
return exfat_write_inode(inode, 0);
|
return exfat_write_inode(inode, 0);
|
||||||
#else
|
#else
|
||||||
return exfat_write_inode(inode, NULL);
|
return exfat_write_inode(inode, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
return __exfat_write_inode(inode, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct inode *exfat_alloc_inode(struct super_block *sb)
|
static struct inode *exfat_alloc_inode(struct super_block *sb)
|
||||||
|
@ -2016,6 +2202,7 @@ static int exfat_write_inode(struct inode *inode, int wait)
|
||||||
static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
|
static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
DIR_ENTRY_T info;
|
DIR_ENTRY_T info;
|
||||||
|
@ -2033,6 +2220,11 @@ static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
FsWriteStat(inode, &info);
|
FsWriteStat(inode, &info);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
if (inode->i_ino == EXFAT_ROOT_INO)
|
||||||
|
return 0;
|
||||||
|
return __exfat_write_inode(inode, 0);;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
|
||||||
|
@ -2586,7 +2778,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
goto out_fail2;
|
goto out_fail2;
|
||||||
root_inode->i_ino = EXFAT_ROOT_INO;
|
root_inode->i_ino = EXFAT_ROOT_INO;
|
||||||
SET_IVERSION(root_inode, 1);
|
SET_IVERSION(root_inode, 1);
|
||||||
|
|
||||||
error = exfat_read_root(root_inode);
|
error = exfat_read_root(root_inode);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto out_fail2;
|
goto out_fail2;
|
||||||
|
|
|
@ -38,6 +38,17 @@
|
||||||
#include "exfat_api.h"
|
#include "exfat_api.h"
|
||||||
#include "exfat_core.h"
|
#include "exfat_core.h"
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||||
|
#include <linux/iversion.h>
|
||||||
|
#define INC_IVERSION(x) (inode_inc_iversion(x))
|
||||||
|
#define GET_IVERSION(x) (inode_peek_iversion_raw(x))
|
||||||
|
#define SET_IVERSION(x,y) (inode_set_iversion(x, y))
|
||||||
|
#else
|
||||||
|
#define INC_IVERSION(x) (x->i_version++)
|
||||||
|
#define GET_IVERSION(x) (x->i_version)
|
||||||
|
#define SET_IVERSION(x,y) (x->i_version = y)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */
|
#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */
|
||||||
#define EXFAT_ERRORS_PANIC 2 /* panic on error */
|
#define EXFAT_ERRORS_PANIC 2 /* panic on error */
|
||||||
#define EXFAT_ERRORS_RO 3 /* remount r/o on error */
|
#define EXFAT_ERRORS_RO 3 /* remount r/o on error */
|
||||||
|
@ -45,6 +56,18 @@
|
||||||
/* ioctl command */
|
/* ioctl command */
|
||||||
#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32)
|
#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32)
|
||||||
|
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
#define EXFAT_IOCTL_READDIR_DIRECT _IOR('r', 0x13, DIR_ENTRY_T)
|
||||||
|
#define EXFAT_IOCTL_SET_DELAY_SYNC _IOR('r', 0x14, __u32)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long is_delay_sync;
|
||||||
|
struct inode *dir_inode;
|
||||||
|
} EXFAT_DELAY_SYNC;
|
||||||
|
|
||||||
|
#define EXFAT_IS_DELAY_SYNC(sbi, node) (sbi->delay_sync.is_delay_sync && node == sbi->delay_sync.dir_inode)
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
|
|
||||||
struct exfat_mount_options {
|
struct exfat_mount_options {
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
|
||||||
kuid_t fs_uid;
|
kuid_t fs_uid;
|
||||||
|
@ -93,6 +116,9 @@ struct exfat_sb_info {
|
||||||
#ifdef CONFIG_EXFAT_KERNEL_DEBUG
|
#ifdef CONFIG_EXFAT_KERNEL_DEBUG
|
||||||
long debug_flags;
|
long debug_flags;
|
||||||
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
|
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
|
||||||
|
#ifdef FSLINUX_IOCTL_ENABLE
|
||||||
|
EXFAT_DELAY_SYNC delay_sync;
|
||||||
|
#endif /* FSLINUX_IOCTL_ENABLE */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user