fs: sdfat: Update to version 2.3.0

* Samsung version G975FXXU3BSKO

Change-Id: I11a2c361ba70441d2a75188a4f91d3cd324d1a9e
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
Kevin F. Haggerty 2019-12-13 16:38:33 -07:00 committed by ripee
parent ab4d4ec6ff
commit 21fd5d5610
10 changed files with 238 additions and 51 deletions

View File

@ -120,3 +120,8 @@ config SDFAT_STATISTICS
bool "Enable statistics for bigdata"
depends on SDFAT_FS
default y
config SDFAT_UEVENT
bool "Enable uevent"
depends on SDFAT_FS
default y

View File

@ -98,6 +98,14 @@ typedef struct {
/* Type Definitions */
/*----------------------------------------------------------------------*/
/* should be merged it to DATE_TIME_T */
typedef union {
struct {
u8 off : 7;
u8 valid : 1;
};
u8 value;
} TIMEZONE_T;
typedef struct {
u16 sec; /* 0 ~ 59 */
u16 min; /* 0 ~ 59 */
@ -105,9 +113,9 @@ typedef struct {
u16 day; /* 1 ~ 31 */
u16 mon; /* 1 ~ 12 */
u16 year; /* 0 ~ 127 (since 1980) */
TIMEZONE_T tz;
} TIMESTAMP_T;
typedef struct {
u16 Year;
u16 Month;
@ -116,6 +124,7 @@ typedef struct {
u16 Minute;
u16 Second;
u16 MilliSecond;
TIMEZONE_T Timezone;
} DATE_TIME_T;
typedef struct {

View File

@ -33,12 +33,27 @@
#include <linux/writeback.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#include <linux/iversion.h>
#endif
#include "sdfat.h"
#include "core.h"
#include <asm/byteorder.h>
#include <asm/unaligned.h>
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
static inline u64 inode_peek_iversion(struct inode *inode)
{
return inode->i_version;
}
#endif
/*----------------------------------------------------------------------*/
/* Constant & Macro Definitions */
/*----------------------------------------------------------------------*/
@ -1956,10 +1971,10 @@ s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid)
return ret;
/* check the validation of hint_stat and initialize it if required */
if (dir_fid->version != (u32)(GET_IVERSION(inode) & 0xffffffff)) {
if (dir_fid->version != (u32)inode_peek_iversion(inode)) {
dir_fid->hint_stat.clu = dir.dir;
dir_fid->hint_stat.eidx = 0;
dir_fid->version = (u32)(GET_IVERSION(inode) & 0xffffffff);
dir_fid->version = (u32)inode_peek_iversion(inode);
dir_fid->hint_femp.eidx = -1;
}
@ -2956,6 +2971,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
info->CreateTimestamp.Minute = tm.min;
info->CreateTimestamp.Second = tm.sec;
info->CreateTimestamp.MilliSecond = 0;
info->CreateTimestamp.Timezone.value = tm.tz.value;
fsi->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
info->ModifyTimestamp.Year = tm.year;
@ -2965,6 +2981,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
info->ModifyTimestamp.Minute = tm.min;
info->ModifyTimestamp.Second = tm.sec;
info->ModifyTimestamp.MilliSecond = 0;
info->ModifyTimestamp.Timezone.value = tm.tz.value;
memset((s8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
@ -3067,6 +3084,7 @@ s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync)
fsi->fs_func->set_entry_attr(ep, info->Attr);
/* set FILE_INFO structure using the acquired DENTRY_T */
tm.tz = info->CreateTimestamp.Timezone;
tm.sec = info->CreateTimestamp.Second;
tm.min = info->CreateTimestamp.Minute;
tm.hour = info->CreateTimestamp.Hour;
@ -3075,6 +3093,7 @@ s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync)
tm.year = info->CreateTimestamp.Year;
fsi->fs_func->set_entry_time(ep, &tm, TM_CREATE);
tm.tz = info->ModifyTimestamp.Timezone;
tm.sec = info->ModifyTimestamp.Second;
tm.min = info->ModifyTimestamp.Minute;
tm.hour = info->ModifyTimestamp.Hour;

View File

@ -222,24 +222,28 @@ static void exfat_set_entry_size(DENTRY_T *p_entry, u64 size)
static void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
{
u16 t = 0x00, d = 0x21;
u16 t = 0x00, d = 0x21, tz = 0x00;
FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry;
switch (mode) {
case TM_CREATE:
t = le16_to_cpu(ep->create_time);
d = le16_to_cpu(ep->create_date);
tz = ep->create_tz;
break;
case TM_MODIFY:
t = le16_to_cpu(ep->modify_time);
d = le16_to_cpu(ep->modify_date);
tz = ep->modify_tz;
break;
case TM_ACCESS:
t = le16_to_cpu(ep->access_time);
d = le16_to_cpu(ep->access_date);
tz = ep->access_tz;
break;
}
tp->tz.value = tz;
tp->sec = (t & 0x001F) << 1;
tp->min = (t >> 5) & 0x003F;
tp->hour = (t >> 11);
@ -260,14 +264,17 @@ static void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
case TM_CREATE:
ep->create_time = cpu_to_le16(t);
ep->create_date = cpu_to_le16(d);
ep->create_tz = tp->tz.value;
break;
case TM_MODIFY:
ep->modify_time = cpu_to_le16(t);
ep->modify_date = cpu_to_le16(d);
ep->modify_tz = tp->tz.value;
break;
case TM_ACCESS:
ep->access_time = cpu_to_le16(t);
ep->access_date = cpu_to_le16(d);
ep->access_tz = tp->tz.value;
break;
}
} /* end of exfat_set_entry_time */
@ -285,7 +292,6 @@ static void __init_file_entry(struct super_block *sb, FILE_DENTRY_T *ep, u32 typ
exfat_set_entry_time((DENTRY_T *) ep, tp, TM_ACCESS);
ep->create_time_ms = 0;
ep->modify_time_ms = 0;
ep->access_time_ms = 0;
} /* end of __init_file_entry */
static void __init_strm_entry(STRM_DENTRY_T *ep, u8 flags, u32 start_clu, u64 size)

View File

@ -441,6 +441,7 @@ static void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
break;
}
tp->tz.value = 0x00;
tp->sec = (t & 0x001F) << 1;
tp->min = (t >> 5) & 0x003F;
tp->hour = (t >> 11);

View File

@ -52,6 +52,58 @@
#define ST_LOG(fmt, ...)
#endif
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
#define CURRENT_TIME_SEC timespec64_trunc(current_kernel_time64(), NSEC_PER_SEC)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
#define CURRENT_TIME_SEC timespec_trunc(current_kernel_time(), NSEC_PER_SEC)
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
/* EMPTY */
#endif
#ifdef CONFIG_SDFAT_UEVENT
static struct kobject sdfat_uevent_kobj;
int sdfat_uevent_init(struct kset *sdfat_kset)
{
int err;
struct kobj_type *ktype = get_ktype(&sdfat_kset->kobj);
sdfat_uevent_kobj.kset = sdfat_kset;
err = kobject_init_and_add(&sdfat_uevent_kobj, ktype, NULL, "uevent");
if (err)
pr_err("[SDFAT] Unable to create sdfat uevent kobj\n");
return err;
}
void sdfat_uevent_uninit(void)
{
kobject_del(&sdfat_uevent_kobj);
memset(&sdfat_uevent_kobj, 0, sizeof(struct kobject));
}
void sdfat_uevent_ro_remount(struct super_block *sb)
{
struct block_device *bdev = sb->s_bdev;
dev_t bd_dev = bdev ? bdev->bd_dev : 0;
char major[16], minor[16];
char *envp[] = { major, minor, NULL };
snprintf(major, sizeof(major), "MAJOR=%d", MAJOR(bd_dev));
snprintf(minor, sizeof(minor), "MINOR=%d", MINOR(bd_dev));
kobject_uevent_env(&sdfat_uevent_kobj, KOBJ_CHANGE, envp);
ST_LOG("[SDFAT](%s[%d:%d]): Uevent triggered\n",
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
}
#endif
/*
* sdfat_fs_error reports a file system problem that might indicate fa data
* corruption/inconsistency. Depending on 'errors' mount option the
@ -99,6 +151,7 @@ void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
ST_LOG("[SDFAT](%s[%d:%d]): Filesystem has been set read-only\n",
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
#endif
sdfat_uevent_ro_remount(sb);
}
}
EXPORT_SYMBOL(__sdfat_fs_error);
@ -174,9 +227,10 @@ static time_t accum_days_in_year[] = {
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
};
#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN)
/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
DATE_TIME_T *tp)
void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
DATE_TIME_T *tp)
{
time_t year = tp->Year;
time_t ld; /* leap day */
@ -191,22 +245,45 @@ void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
+ (year * 365 + ld + accum_days_in_year[tp->Month]
+ (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY;
if (!sbi->options.tz_utc)
ts->tv_sec += sys_tz.tz_minuteswest * SECS_PER_MIN;
ts->tv_nsec = 0;
/* Treat as local time */
if (!sbi->options.tz_utc && !tp->Timezone.valid) {
ts->tv_sec += sys_tz.tz_minuteswest * SECS_PER_MIN;
return;
}
/* Treat as UTC time */
if (!tp->Timezone.valid)
return;
/* Treat as UTC time, but need to adjust timezone to UTC0 */
if (tp->Timezone.off <= 0x3F)
ts->tv_sec -= TIMEZONE_SEC(tp->Timezone.off);
else /* 0x40 <= (tp->Timezone & 0x7F) <=0x7F */
ts->tv_sec += TIMEZONE_SEC(0x80 - tp->Timezone.off);
}
#define TIMEZONE_CUR_OFFSET() ((sys_tz.tz_minuteswest / (-15)) & 0x7F)
/* Convert linear UNIX date to a FAT time/date pair. */
void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
DATE_TIME_T *tp)
void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
DATE_TIME_T *tp)
{
bool tz_valid = (sbi->fsi.vol_type == EXFAT) ? true : false;
time_t second = ts->tv_sec;
time_t day, month, year;
time_t ld; /* leap day */
if (!sbi->options.tz_utc)
tp->Timezone.value = 0x00;
/* Treats as local time with proper time */
if (tz_valid || !sbi->options.tz_utc) {
second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
if (tz_valid) {
tp->Timezone.valid = 1;
tp->Timezone.off = TIMEZONE_CUR_OFFSET();
}
}
/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
if (second < UNIX_SECS_1980) {
@ -262,7 +339,7 @@ void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp)
{
struct timespec_compat ts = CURRENT_TIME_SEC;
sdfat_timespec_t ts = CURRENT_TIME_SEC;
DATE_TIME_T dt;
sdfat_time_unix2fat(sbi, &ts, &dt);
@ -273,6 +350,7 @@ TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp)
tp->hour = dt.Hour;
tp->min = dt.Minute;
tp->sec = dt.Second;
tp->tz.value = dt.Timezone.value;
return tp;
}

View File

@ -54,7 +54,9 @@
#include <linux/vmalloc.h>
#include <asm/current.h>
#include <asm/unaligned.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#include <linux/iversion.h>
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
#include <linux/aio.h>
#endif
@ -138,6 +140,18 @@ static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len,
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
static inline void inode_set_iversion(struct inode *inode, u64 val)
{
inode->i_version = val;
}
static inline u64 inode_peek_iversion(struct inode *inode)
{
return inode->i_version;
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
/* EMPTY */
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) */
@ -889,6 +903,15 @@ static int sdfat_file_fsync(struct file *filp, int datasync)
/*************************************************************************
* MORE FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
#define CURRENT_TIME_SEC timespec64_trunc(current_kernel_time64(), NSEC_PER_SEC)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
#define CURRENT_TIME_SEC timespec_trunc(current_kernel_time(), NSEC_PER_SEC)
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
/* EMPTY */
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
static void sdfat_writepage_end_io(struct bio *bio)
{
@ -1215,7 +1238,8 @@ static int __sdfat_revalidate_common(struct dentry *dentry)
spin_lock(&dentry->d_lock);
if ((!dentry->d_inode) && (!__check_dstate_locked(dentry) &&
(dentry->d_time != GET_IVERSION(dentry->d_parent->d_inode)))) {
(dentry->d_time !=
(unsigned long)inode_peek_iversion(dentry->d_parent->d_inode)))) {
ret = 0;
}
spin_unlock(&dentry->d_lock);
@ -2363,7 +2387,7 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct timespec_compat ts;
sdfat_timespec_t ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@ -2380,7 +2404,7 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
INC_IVERSION(dir);
inode_inc_iversion(dir);
dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
@ -2393,7 +2417,8 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
err = PTR_ERR(inode);
goto out;
}
INC_IVERSION(inode);
inode_inc_iversion(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
@ -2510,7 +2535,7 @@ static struct dentry *__sdfat_lookup(struct inode *dir, struct dentry *dentry)
dput(alias);
out:
/* initialize d_time even though it is positive dentry */
dentry->d_time = GET_IVERSION(dir);
dentry->d_time = (unsigned long)inode_peek_iversion(dir);
__unlock_super(sb);
dentry = d_splice_alias(inode, dentry);
@ -2528,7 +2553,8 @@ static int sdfat_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
struct timespec_compat ts;
sdfat_timespec_t ts;
int err;
__lock_super(sb);
@ -2547,7 +2573,7 @@ static int sdfat_unlink(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
INC_IVERSION(dir);
inode_inc_iversion(dir);
dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
@ -2557,7 +2583,7 @@ static int sdfat_unlink(struct inode *dir, struct dentry *dentry)
clear_nlink(inode);
inode->i_mtime = inode->i_atime = ts;
sdfat_detach(inode);
dentry->d_time = GET_IVERSION(dir);
dentry->d_time = (unsigned long)inode_peek_iversion(dir);
out:
__unlock_d_revalidate(dentry);
__unlock_super(sb);
@ -2569,7 +2595,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct timespec_compat ts;
sdfat_timespec_t ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@ -2599,7 +2625,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
__lock_d_revalidate(dentry);
INC_IVERSION(dir);
inode_inc_iversion(dir);
dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
@ -2612,7 +2638,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
err = PTR_ERR(inode);
goto out;
}
INC_IVERSION(inode);
inode_inc_iversion(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
@ -2636,7 +2662,7 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct timespec_compat ts;
sdfat_timespec_t ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@ -2653,7 +2679,7 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
INC_IVERSION(dir);
inode_inc_iversion(dir);
dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
@ -2667,7 +2693,8 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
err = PTR_ERR(inode);
goto out;
}
INC_IVERSION(inode);
inode_inc_iversion(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
@ -2687,7 +2714,7 @@ static int sdfat_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
struct timespec_compat ts;
sdfat_timespec_t ts;
int err;
__lock_super(sb);
@ -2704,7 +2731,7 @@ static int sdfat_rmdir(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
INC_IVERSION(dir);
inode_inc_iversion(dir);
dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
@ -2715,7 +2742,7 @@ static int sdfat_rmdir(struct inode *dir, struct dentry *dentry)
clear_nlink(inode);
inode->i_mtime = inode->i_atime = ts;
sdfat_detach(inode);
dentry->d_time = GET_IVERSION(dir);
dentry->d_time = (unsigned long)inode_peek_iversion(dir);
out:
__unlock_d_revalidate(dentry);
__unlock_super(sb);
@ -2728,7 +2755,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
{
struct inode *old_inode, *new_inode;
struct super_block *sb = old_dir->i_sb;
struct timespec_compat ts;
sdfat_timespec_t ts;
loff_t i_pos;
int err;
@ -2752,7 +2779,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
__lock_d_revalidate(old_dentry);
__lock_d_revalidate(new_dentry);
INC_IVERSION(new_dir);
inode_inc_iversion(new_dir);
new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts;
if (IS_DIRSYNC(new_dir))
(void) sdfat_sync_inode(new_dir);
@ -2773,7 +2800,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
inc_nlink(new_dir);
}
INC_IVERSION(old_dir);
inode_inc_iversion(old_dir);
old_dir->i_ctime = old_dir->i_mtime = ts;
if (IS_DIRSYNC(old_dir))
(void) sdfat_sync_inode(old_dir);
@ -2882,6 +2909,18 @@ static int sdfat_sanitize_mode(const struct sdfat_sb_info *sbi,
return 0;
}
/*
* sdfat_block_truncate_page() zeroes out a mapping from file offset `from'
* up to the end of the block which corresponds to `from'.
* This is required during truncate to physically zeroout the tail end
* of that block so it doesn't yield old data if the file is later grown.
* Also, avoid causing failure from fsx for cases of "data past EOF"
*/
static int sdfat_block_truncate_page(struct inode *inode, loff_t from)
{
return block_truncate_page(inode->i_mapping, from, sdfat_get_block);
}
static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
{
@ -2897,7 +2936,7 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
&& (attr->ia_size > i_size_read(inode))) {
error = sdfat_cont_expand(inode, attr->ia_size);
if (error || attr->ia_valid == ATTR_SIZE)
return error;
goto out;
attr->ia_valid &= ~ATTR_SIZE;
}
@ -2911,7 +2950,7 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
error = setattr_prepare(dentry, attr);
attr->ia_valid = ia_valid;
if (error)
return error;
goto out;
if (((attr->ia_valid & ATTR_UID) &&
(!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
@ -2919,7 +2958,8 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
(!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | S_IRWXUGO)))) {
return -EPERM;
error = -EPERM;
goto out;
}
/*
@ -2935,6 +2975,10 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
/* patch 1.2.0 : fixed the problem of size mismatch. */
if (attr->ia_valid & ATTR_SIZE) {
error = sdfat_block_truncate_page(inode, attr->ia_size);
if (error)
goto out;
old_size = i_size_read(inode);
/* TO CHECK evicting directory works correctly */
@ -2944,8 +2988,7 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
}
setattr_copy(inode, attr);
mark_inode_dirty(inode);
out:
TMSG("%s exited with err(%d)\n", __func__, error);
return error;
}
@ -3894,7 +3937,7 @@ static int sdfat_fill_inode(struct inode *inode, const FILE_ID_T *fid)
SDFAT_I(inode)->target = NULL;
inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid;
INC_IVERSION(inode);
inode_inc_iversion(inode);
inode->i_generation = get_seconds();
if (fsapi_read_inode(inode, &info) < 0) {
@ -3972,7 +4015,7 @@ static struct inode *sdfat_build_inode(struct super_block *sb,
goto out;
}
inode->i_ino = iunique(sb, SDFAT_ROOT_INO);
SET_IVERSION(inode, 1);
inode_set_iversion(inode, 1);
err = sdfat_fill_inode(inode, fid);
if (err) {
iput(inode);
@ -4801,7 +4844,7 @@ static int sdfat_read_root(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
struct timespec_compat ts;
sdfat_timespec_t ts;
FS_INFO_T *fsi = &(sbi->fsi);
DIR_ENTRY_T info;
@ -4827,7 +4870,7 @@ static int sdfat_read_root(struct inode *inode)
inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid;
INC_IVERSION(inode);
inode_inc_iversion(inode);
inode->i_generation = 0;
inode->i_mode = sdfat_make_mode(sbi, ATTR_SUBDIR, S_IRWXUGO);
inode->i_op = &sdfat_dir_inode_operations;
@ -4955,7 +4998,7 @@ static int sdfat_fill_super(struct super_block *sb, void *data, int silent)
}
root_inode->i_ino = SDFAT_ROOT_INO;
SET_IVERSION(root_inode, 1);
inode_set_iversion(root_inode, 1);
err = sdfat_read_root(root_inode);
if (err) {
@ -5127,7 +5170,7 @@ static int __init init_sdfat_fs(void)
sdfat_kset = kset_create_and_add("sdfat", NULL, fs_kobj);
if (!sdfat_kset) {
pr_err("[SDFAT] failed to create fs_kobj\n");
pr_err("[SDFAT] failed to create sdfat kset\n");
err = -ENOMEM;
goto error;
}
@ -5142,6 +5185,10 @@ static int __init init_sdfat_fs(void)
if (err)
goto error;
err = sdfat_uevent_init(sdfat_kset);
if (err)
goto error;
err = sdfat_init_inodecache();
if (err) {
pr_err("[SDFAT] failed to initialize inode cache\n");
@ -5172,6 +5219,7 @@ static int __init init_sdfat_fs(void)
return 0;
error:
sdfat_uevent_uninit();
sdfat_statistics_uninit();
if (sdfat_kset) {
@ -5189,6 +5237,7 @@ error:
static void __exit exit_sdfat_fs(void)
{
sdfat_uevent_uninit();
sdfat_statistics_uninit();
if (sdfat_kset) {

View File

@ -241,6 +241,12 @@ struct sdfat_inode_info {
struct inode vfs_inode;
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
typedef struct timespec64 sdfat_timespec_t;
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) */
typedef struct timespec sdfat_timespec_t;
#endif
/*
* FIXME : needs on-disk-slot in-memory data
*/
@ -382,6 +388,18 @@ static inline void setup_sdfat_xattr_handler(struct super_block *sb) {};
#endif
/* sdfat/misc.c */
#ifdef CONFIG_SDFAT_UEVENT
extern int sdfat_uevent_init(struct kset *sdfat_kset);
extern void sdfat_uevent_uninit(void);
extern void sdfat_uevent_ro_remount(struct super_block *sb);
#else
static inline int sdfat_uevent_init(struct kset *sdfat_kset)
{
return 0;
}
static inline void sdfat_uevent_uninit(void) {};
static inline void sdfat_uevent_ro_remount(struct super_block *sb) {};
#endif
extern void
__sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
__printf(3, 4) __cold;
@ -397,9 +415,9 @@ __sdfat_msg(struct super_block *sb, const char *lv, int st, const char *fmt, ...
#define sdfat_log_msg(sb, lv, fmt, args...) \
__sdfat_msg(sb, lv, 1, fmt, ## args)
extern void sdfat_log_version(void);
extern void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
extern void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
DATE_TIME_T *tp);
extern void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec_compat *ts,
extern void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, sdfat_timespec_t *ts,
DATE_TIME_T *tp);
extern TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tm);

View File

@ -363,8 +363,10 @@ typedef struct {
__le16 access_date; // aligned
__u8 create_time_ms;
__u8 modify_time_ms;
__u8 access_time_ms;
__u8 reserved2[9];
__u8 create_tz;
__u8 modify_tz;
__u8 access_tz;
__u8 reserved2[7];
} FILE_DENTRY_T;
/* EXFAT stream extension directory entry (32 bytes) */

View File

@ -22,4 +22,4 @@
/* PURPOSE : sdFAT File Manager */
/* */
/************************************************************************/
#define SDFAT_VERSION "2.1.8-lineage"
#define SDFAT_VERSION "2.3.0-lineage"