1.修复exfat卡文件系统问题

This commit is contained in:
payton 2023-12-05 11:30:03 +08:00
parent 17f1537ef9
commit dc9361e272
7 changed files with 262 additions and 25 deletions

View File

@ -35,3 +35,4 @@ clean:
.PHONY: modules modules_install clean .PHONY: modules modules_install clean
endif endif

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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 */
}; };
/* /*