aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorderfelot <5124143+derfelot@users.noreply.github.com>2019-01-06 00:33:53 +0100
committerMoyster <oysterized@gmail.com>2019-05-02 14:30:26 +0200
commite74405332aadff45a0b1df198810fe6d55d58482 (patch)
tree18e9825121dbcb195f5cb46984a0d7cc1657b726
parent876de7e5adb6a1f1a4945f7cae1b65e591ff76b4 (diff)
fs: sdfat: Update to version 2.1.8
Taken from SM-G965F_PP_Opensource kernel (G965FXXU2CRLI) Change-Id: Iab9cfefb0cce4001ef0de8c739f1d9c940513e78
-rw-r--r--fs/sdfat/api.c7
-rw-r--r--fs/sdfat/api.h3
-rw-r--r--fs/sdfat/core.c15
-rw-r--r--fs/sdfat/core.h3
-rw-r--r--fs/sdfat/core_fat.c9
-rw-r--r--fs/sdfat/misc.c22
-rw-r--r--fs/sdfat/mpage.c79
-rw-r--r--fs/sdfat/sdfat.c265
-rw-r--r--fs/sdfat/sdfat.h4
-rw-r--r--fs/sdfat/sdfat_fs.h2
-rw-r--r--fs/sdfat/statistics.c11
-rw-r--r--fs/sdfat/version.h2
12 files changed, 277 insertions, 145 deletions
diff --git a/fs/sdfat/api.c b/fs/sdfat/api.c
index 02e0939ef..45b0c4106 100644
--- a/fs/sdfat/api.c
+++ b/fs/sdfat/api.c
@@ -478,6 +478,13 @@ void fsapi_invalidate_extent(struct inode *inode)
}
EXPORT_SYMBOL(fsapi_invalidate_extent);
+/* check device is ejected */
+s32 fsapi_check_bdi_valid(struct super_block *sb)
+{
+ return fscore_check_bdi_valid(sb);
+}
+EXPORT_SYMBOL(fsapi_check_bdi_valid);
+
#ifdef CONFIG_SDFAT_DFR
diff --git a/fs/sdfat/api.h b/fs/sdfat/api.h
index 0bd05d700..df6a32fb8 100644
--- a/fs/sdfat/api.h
+++ b/fs/sdfat/api.h
@@ -355,6 +355,9 @@ u32 fsapi_get_au_stat(struct super_block *sb, s32 mode);
/* extent cache functions */
void fsapi_invalidate_extent(struct inode *inode);
+/* bdev management */
+s32 fsapi_check_bdi_valid(struct super_block *sb);
+
#ifdef CONFIG_SDFAT_DFR
/*----------------------------------------------------------------------*/
/* Defragmentation related */
diff --git a/fs/sdfat/core.c b/fs/sdfat/core.c
index 357eb0d54..618c9e7f7 100644
--- a/fs/sdfat/core.c
+++ b/fs/sdfat/core.c
@@ -1621,6 +1621,12 @@ s32 fscore_shutdown(void)
return 0;
}
+/* check device is ejected */
+s32 fscore_check_bdi_valid(struct super_block *sb)
+{
+ return bdev_check_bdi_valid(sb);
+}
+
static bool is_exfat(pbr_t *pbr)
{
int i = 53;
@@ -1703,6 +1709,7 @@ s32 fscore_mount(struct super_block *sb)
pbr_t *p_pbr;
struct buffer_head *tmp_bh = NULL;
struct gendisk *disk = sb->s_bdev->bd_disk;
+ struct hd_struct *part = sb->s_bdev->bd_part;
struct sdfat_mount_options *opts = &(SDFAT_SB(sb)->options);
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
@@ -1802,9 +1809,11 @@ free_bh:
"misaligned" : "aligned");
sdfat_log_msg(sb, KERN_INFO,
- "detected volume size : %llu MB (disk_size : %llu MB)",
- fsi->num_sectors >> 11,
- disk ? (u64)((disk->part0.nr_sects) >> 11) : 0);
+ "detected volume size : %llu KB (disk : %llu KB, "
+ "part : %llu KB)",
+ (fsi->num_sectors * (sb->s_blocksize >> SECTOR_SIZE_BITS)) >> 1,
+ disk ? (u64)((disk->part0.nr_sects) >> 1) : 0,
+ part ? (u64)((part->nr_sects) >> 1) : 0);
ret = load_upcase_table(sb);
if (ret) {
diff --git a/fs/sdfat/core.h b/fs/sdfat/core.h
index 00ea2c5e2..1f8ed5a28 100644
--- a/fs/sdfat/core.h
+++ b/fs/sdfat/core.h
@@ -70,6 +70,9 @@ typedef struct {
s32 fscore_init(void);
s32 fscore_shutdown(void);
+/* bdev management */
+s32 fscore_check_bdi_valid(struct super_block *sb);
+
/* chain management */
s32 chain_cont_cluster(struct super_block *sb, u32 chain, u32 len);
diff --git a/fs/sdfat/core_fat.c b/fs/sdfat/core_fat.c
index 493e5cb7e..d25ec32d3 100644
--- a/fs/sdfat/core_fat.c
+++ b/fs/sdfat/core_fat.c
@@ -1323,8 +1323,9 @@ static sector_t __calc_hidden_sect(struct super_block *sb)
hidden = bdev->bd_part->start_sect;
/* a disk device, not a partition */
if (!hidden) {
- ASSERT(bdev == bdev->bd_contains);
- ASSERT(!bdev->bd_part->partno);
+ if (bdev != bdev->bd_contains)
+ sdfat_log_msg(sb, KERN_WARNING,
+ "hidden(0), but disk has a partition table");
goto out;
}
@@ -1334,8 +1335,8 @@ static sector_t __calc_hidden_sect(struct super_block *sb)
}
out:
- sdfat_log_msg(sb, KERN_INFO, "start_sect of partition : %lld",
- (s64)hidden);
+ sdfat_log_msg(sb, KERN_INFO, "start_sect of part(%d) : %lld",
+ bdev ? bdev->bd_part->partno : -1, (s64)hidden);
return hidden;
}
diff --git a/fs/sdfat/misc.c b/fs/sdfat/misc.c
index b9592ef4c..9b07d1dea 100644
--- a/fs/sdfat/misc.c
+++ b/fs/sdfat/misc.c
@@ -43,11 +43,23 @@
#include "version.h"
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
+#ifdef CONFIG_PROC_FSLOG
+#include <linux/fslog.h>
+#else
#include <linux/stlog.h>
+#endif
#else
#define ST_LOG(fmt, ...)
#endif
+/*************************************************************************
+ * FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
+ *************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+#define CURRENT_TIME_SEC timespec_trunc(current_kernel_time(), NSEC_PER_SEC)
+#endif
+
+
/*
* sdfat_fs_error reports a file system problem that might indicate fa data
* corruption/inconsistency. Depending on 'errors' mount option the
@@ -84,6 +96,7 @@ void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
} else if (opts->errors == SDFAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) {
sb->s_flags |= MS_RDONLY;
+ sdfat_statistics_set_mnt_ro();
pr_err("[SDFAT](%s[%d:%d]): Filesystem has been set "
"read-only\n", sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
@@ -253,15 +266,9 @@ void sdfat_time_unix2fat(struct sdfat_sb_info *sbi, struct timespec *ts,
TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp)
{
- struct timespec ts;
+ struct timespec ts = CURRENT_TIME_SEC;
DATE_TIME_T dt;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
- ts = CURRENT_TIME_SEC;
-#else
- ktime_get_real_ts(&ts);
-#endif
-
sdfat_time_unix2fat(sbi, &ts, &dt);
tp->year = dt.Year;
@@ -384,3 +391,4 @@ void __sdfat_dmsg(int level, const char *fmt, ...)
#endif
}
#endif
+
diff --git a/fs/sdfat/mpage.c b/fs/sdfat/mpage.c
index b39858258..f550fbb22 100644
--- a/fs/sdfat/mpage.c
+++ b/fs/sdfat/mpage.c
@@ -78,6 +78,27 @@ static void __mpage_write_end_io(struct bio *bio, int err);
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+ /* EMPTY */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) */
+static inline void bio_set_dev(struct bio *bio, struct block_device *bdev)
+{
+ bio->bi_bdev = bdev;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+static inline void __sdfat_clean_bdev_aliases(struct block_device *bdev, sector_t block)
+{
+ clean_bdev_aliases(bdev, block, 1);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) */
+static inline void __sdfat_clean_bdev_aliases(struct block_device *bdev, sector_t block)
+{
+ unmap_underlying_metadata(bdev, block);
+}
+#endif
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio)
{
@@ -91,24 +112,6 @@ static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio)
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
-static void mpage_write_end_io(struct bio *bio)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
- __mpage_write_end_io(bio, bio->bi_status);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
- __mpage_write_end_io(bio, bio->bi_error);
-#endif
-}
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) */
-static void mpage_write_end_io(struct bio *bio, int err)
-{
- if (test_bit(BIO_UPTODATE, &bio->bi_flags))
- err = 0;
- __mpage_write_end_io(bio, err);
-}
-#endif
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static inline int bio_get_nr_vecs(struct block_device *bdev)
{
@@ -160,6 +163,28 @@ static inline void __sdfat_set_bio_size(struct bio *bio, unsigned int size)
}
#endif
+/*************************************************************************
+ * MORE FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
+ *************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+static void mpage_write_end_io(struct bio *bio)
+{
+ __mpage_write_end_io(bio, blk_status_to_errno(bio->bi_status));
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
+static void mpage_write_end_io(struct bio *bio)
+{
+ __mpage_write_end_io(bio, bio->bi_error);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) */
+static void mpage_write_end_io(struct bio *bio, int err)
+{
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ err = 0;
+ __mpage_write_end_io(bio, err);
+}
+#endif
+
/* __check_dfr_on() and __dfr_writepage_end_io() functions
* are copied from sdfat.c
* Each function should be same perfectly
@@ -281,11 +306,7 @@ mpage_alloc(struct block_device *bdev,
}
if (bio) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
bio_set_dev(bio, bdev);
-#else
- bio->bi_bdev = bdev;
-#endif
__sdfat_set_bio_sector(bio, first_sector);
}
return bio;
@@ -369,11 +390,7 @@ static int sdfat_mpage_writepage(struct page *page,
if (buffer_new(bh)) {
clear_buffer_new(bh);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
- clean_bdev_bh_alias(bh);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
- unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
-#endif
+ __sdfat_clean_bdev_aliases(bh->b_bdev, bh->b_blocknr);
}
}
@@ -423,12 +440,7 @@ static int sdfat_mpage_writepage(struct page *page,
goto confused;
if (buffer_new(&map_bh))
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
- clean_bdev_bh_alias(&map_bh);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
- unmap_underlying_metadata(map_bh.b_bdev,
- map_bh.b_blocknr);
-#endif
+ __sdfat_clean_bdev_aliases(map_bh.b_bdev, map_bh.b_blocknr);
if (buffer_boundary(&map_bh)) {
boundary_block = map_bh.b_blocknr;
boundary_bdev = map_bh.b_bdev;
@@ -620,3 +632,4 @@ int sdfat_mpage_writepages(struct address_space *mapping,
}
#endif /* CONFIG_SDFAT_ALIGNED_MPAGE_WRITE */
+
diff --git a/fs/sdfat/sdfat.c b/fs/sdfat/sdfat.c
index 069f6b538..228fb6677 100644
--- a/fs/sdfat/sdfat.c
+++ b/fs/sdfat/sdfat.c
@@ -68,9 +68,6 @@
/* skip iterating emit_dots when dir is empty */
#define ITER_POS_FILLED_DOTS (2)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
-#define current_time(x) (CURRENT_TIME_SEC)
-#endif
/* type index declare at sdfat.h */
const char *FS_TYPE_STR[] = {
"auto",
@@ -112,6 +109,7 @@ static void sdfat_free_namebuf(DENTRY_NAMEBUF_T *nb);
/*************************************************************************
* INNER FUNCTIONS FOR FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
+static int __sdfat_getattr(struct inode *inode, struct kstat *stat);
static void __sdfat_writepage_end_io(struct bio *bio, int err);
static inline void __lock_super(struct super_block *sb);
static inline void __unlock_super(struct super_block *sb);
@@ -140,6 +138,51 @@ static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len,
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+ /* EMPTY */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) */
+static inline void bio_set_dev(struct bio *bio, struct block_device *bdev)
+{
+ bio->bi_bdev = bdev;
+}
+#endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+#define CURRENT_TIME_SEC timespec_trunc(current_kernel_time(), NSEC_PER_SEC)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+static int sdfat_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int query_flags)
+{
+ struct inode *inode = d_backing_inode(path->dentry);
+
+ return __sdfat_getattr(inode, stat);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) */
+static int sdfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+
+ return __sdfat_getattr(inode, stat);
+}
+#endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
+static inline void __sdfat_clean_bdev_aliases(struct block_device *bdev, sector_t block)
+{
+ clean_bdev_aliases(bdev, block, 1);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) */
+static inline void __sdfat_clean_bdev_aliases(struct block_device *bdev, sector_t block)
+{
+ unmap_underlying_metadata(bdev, block);
+}
+#endif
+
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
@@ -219,25 +262,6 @@ static inline void inode_unlock(struct inode *inode)
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
-static void sdfat_writepage_end_io(struct bio *bio)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
- __sdfat_writepage_end_io(bio, bio->bi_status);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
- __sdfat_writepage_end_io(bio, bio->bi_error);
-#endif
-}
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
-static void sdfat_writepage_end_io(struct bio *bio, int err)
-{
- if (test_bit(BIO_UPTODATE, &bio->bi_flags))
- err = 0;
- __sdfat_writepage_end_io(bio, err);
-}
-#endif
-
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
static inline int sdfat_remount_syncfs(struct super_block *sb)
{
@@ -870,6 +894,26 @@ static int sdfat_file_fsync(struct file *filp, int datasync)
/*************************************************************************
* MORE FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
+static void sdfat_writepage_end_io(struct bio *bio)
+{
+ __sdfat_writepage_end_io(bio, blk_status_to_errno(bio->bi_status));
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
+static void sdfat_writepage_end_io(struct bio *bio)
+{
+ __sdfat_writepage_end_io(bio, bio->bi_error);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
+static void sdfat_writepage_end_io(struct bio *bio, int err)
+{
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ err = 0;
+ __sdfat_writepage_end_io(bio, err);
+}
+#endif
+
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
static int sdfat_cmp(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
@@ -910,30 +954,6 @@ static int sdfat_cmpi(const struct dentry *parent, const struct inode *pinode,
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
-static const char *sdfat_follow_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
-{
- struct sdfat_inode_info *ei = SDFAT_I(inode);
-
- return (char *)(ei->target);
-}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
-static const char *sdfat_follow_link(struct dentry *dentry, void **cookie)
-{
- struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
-
- return *cookie = (char *)(ei->target);
-}
-#else
-static void *sdfat_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
-
- nd_set_link(nd, (char *)(ei->target));
- return NULL;
-}
-#endif
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
static ssize_t sdfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
@@ -1041,6 +1061,31 @@ static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb,
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+static const char *sdfat_follow_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(inode);
+
+ return (char *)(ei->target);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+static const char *sdfat_follow_link(struct dentry *dentry, void **cookie)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
+
+ return *cookie = (char *)(ei->target);
+}
+#else
+static void *sdfat_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
+
+ nd_set_link(nd, (char *)(ei->target));
+ return NULL;
+}
+#endif
+
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
static int sdfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool excl)
@@ -2221,6 +2266,16 @@ static long sdfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned lo
return sdfat_dbg_ioctl(inode, filp, cmd, arg);
}
+static int __sdfat_getattr(struct inode *inode, struct kstat *stat)
+{
+ TMSG("%s entered\n", __func__);
+
+ generic_fillattr(inode, stat);
+ stat->blksize = SDFAT_SB(inode->i_sb)->fsi.cluster_size;
+
+ TMSG("%s exited\n", __func__);
+ return 0;
+}
static void __sdfat_writepage_end_io(struct bio *bio, int err)
{
@@ -2313,6 +2368,7 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
+ struct timespec ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@@ -2321,6 +2377,8 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
TMSG("%s entered\n", __func__);
+ ts = CURRENT_TIME_SEC;
+
err = fsapi_create(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid);
if (err)
goto out;
@@ -2328,7 +2386,7 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
dir->i_version++;
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
else
@@ -2341,7 +2399,7 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry)
goto out;
}
inode->i_version++;
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode);
@@ -2475,12 +2533,15 @@ 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 ts;
int err;
__lock_super(sb);
TMSG("%s entered\n", __func__);
+ ts = CURRENT_TIME_SEC;
+
SDFAT_I(inode)->fid.size = i_size_read(inode);
__cancel_dfr_work(inode, 0, SDFAT_I(inode)->fid.size, __func__);
@@ -2492,14 +2553,14 @@ static int sdfat_unlink(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
dir->i_version++;
- dir->i_mtime = dir->i_atime = current_time(dir);
+ dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
else
mark_inode_dirty(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ inode->i_mtime = inode->i_atime = ts;
sdfat_detach(inode);
dentry->d_time = dir->i_version;
out:
@@ -2513,6 +2574,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 ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@@ -2527,6 +2589,8 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
TMSG("%s entered\n", __func__);
+ ts = CURRENT_TIME_SEC;
+
err = fsapi_create(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid);
if (err)
goto out;
@@ -2541,7 +2605,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
__lock_d_revalidate(dentry);
dir->i_version++;
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
else
@@ -2554,7 +2618,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
goto out;
}
inode->i_version++;
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
SDFAT_I(inode)->target = kmalloc((len+1), GFP_KERNEL);
@@ -2577,6 +2641,7 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
+ struct timespec ts;
FILE_ID_T fid;
loff_t i_pos;
int err;
@@ -2585,6 +2650,8 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
TMSG("%s entered\n", __func__);
+ ts = CURRENT_TIME_SEC;
+
err = fsapi_mkdir(dir, (u8 *) dentry->d_name.name, &fid);
if (err)
goto out;
@@ -2592,7 +2659,7 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
dir->i_version++;
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ dir->i_ctime = dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
else
@@ -2606,7 +2673,7 @@ static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry)
goto out;
}
inode->i_version++;
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
d_instantiate(dentry, inode);
@@ -2625,12 +2692,15 @@ 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 ts;
int err;
__lock_super(sb);
TMSG("%s entered\n", __func__);
+ ts = CURRENT_TIME_SEC;
+
SDFAT_I(inode)->fid.size = i_size_read(inode);
err = fsapi_rmdir(dir, &(SDFAT_I(inode)->fid));
@@ -2640,7 +2710,7 @@ static int sdfat_rmdir(struct inode *dir, struct dentry *dentry)
__lock_d_revalidate(dentry);
dir->i_version++;
- dir->i_mtime = dir->i_atime = current_time(dir);
+ dir->i_mtime = dir->i_atime = ts;
if (IS_DIRSYNC(dir))
(void) sdfat_sync_inode(dir);
else
@@ -2648,7 +2718,7 @@ static int sdfat_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ inode->i_mtime = inode->i_atime = ts;
sdfat_detach(inode);
dentry->d_time = dir->i_version;
out:
@@ -2663,6 +2733,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 ts;
loff_t i_pos;
int err;
@@ -2673,6 +2744,8 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode;
+ ts = CURRENT_TIME_SEC;
+
SDFAT_I(old_inode)->fid.size = i_size_read(old_inode);
__cancel_dfr_work(old_inode, 0, 1, __func__);
@@ -2685,7 +2758,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
__lock_d_revalidate(new_dentry);
new_dir->i_version++;
- new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = current_time(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);
else
@@ -2706,7 +2779,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
}
old_dir->i_version++;
- old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
+ old_dir->i_ctime = old_dir->i_mtime = ts;
if (IS_DIRSYNC(old_dir))
(void) sdfat_sync_inode(old_dir);
else
@@ -2725,7 +2798,7 @@ static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
__func__);
WARN_ON(new_inode->i_nlink == 0);
}
- new_inode->i_ctime = current_time(new_inode);
+ new_inode->i_ctime = ts;
#if 0
(void) sdfat_sync_inode(new_inode);
#endif
@@ -2749,7 +2822,7 @@ static int sdfat_cont_expand(struct inode *inode, loff_t size)
if (err)
return err;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
if (!IS_SYNC(inode))
@@ -2882,25 +2955,6 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
return error;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
-static int sdfat_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags)
-{
- struct inode *inode = path->dentry->d_inode;
-#else
-static int sdfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
- struct inode *inode = dentry->d_inode;
-#endif
-
- TMSG("%s entered\n", __func__);
-
- generic_fillattr(inode, stat);
- stat->blksize = SDFAT_SB(inode->i_sb)->fsi.cluster_size;
-
- TMSG("%s exited\n", __func__);
- return 0;
-}
-
static const struct inode_operations sdfat_dir_inode_operations = {
.create = sdfat_create,
.lookup = sdfat_lookup,
@@ -3010,7 +3064,7 @@ static void sdfat_truncate(struct inode *inode, loff_t old_size)
if (err)
goto out;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
if (IS_DIRSYNC(inode))
(void) sdfat_sync_inode(inode);
else
@@ -3107,7 +3161,7 @@ static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
if (((fsi->vol_type == FAT12) || (fsi->vol_type == FAT16)) &&
(inode->i_ino == SDFAT_ROOT_INO)) {
if (sector < (fsi->dentries_in_root >>
- (sb->s_blocksize_bits-DENTRY_SIZE_BITS))) {
+ (sb->s_blocksize_bits - DENTRY_SIZE_BITS))) {
*phys = sector + fsi->root_start_sector;
*mapped_blocks = 1;
}
@@ -3216,7 +3270,17 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
} else if (create == 1) {
/* Not exist: new cluster needed */
- BUG_ON(!BLOCK_ADDED(bmap_create));
+ if (!BLOCK_ADDED(bmap_create)) {
+ sector_t last_block;
+ last_block = (i_size_read(inode) + (sb->s_blocksize - 1))
+ >> sb->s_blocksize_bits;
+ sdfat_fs_error(sb, "%s: new cluster need, but "
+ "bmap_create == BMAP_NOT_CREATE(iblock:%lld, "
+ "last_block:%lld)", __func__,
+ (s64)iblock, (s64)last_block);
+ err = -EIO;
+ goto unlock_ret;
+ }
// Reserved Cluster (only if iblock is the first sector in a clu)
if (sec_offset == 0) {
@@ -3444,11 +3508,7 @@ static inline void sdfat_submit_fullpage_bio(struct block_device *bdev,
*/
bio = bio_alloc(GFP_NOIO, 1);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
bio_set_dev(bio, bdev);
-#else
- bio->bi_bdev = bdev;
-#endif
bio->bi_vcnt = 1;
bio->bi_io_vec[0].bv_page = page; /* Inline vec */
bio->bi_io_vec[0].bv_len = length; /* PAGE_SIZE */
@@ -3539,11 +3599,7 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
if (buffer_new(bh)) {
clear_buffer_new(bh);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
- clean_bdev_bh_alias(bh);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) */
- unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
-#endif
+ __sdfat_clean_bdev_aliases(bh->b_bdev, bh->b_blocknr);
}
}
@@ -3593,7 +3649,7 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
atomic_inc(&SDFAT_SB(sb)->stat_n_pages_queued);
sdfat_submit_fullpage_bio(head->b_bdev,
- head->b_blocknr << (inode->i_blkbits - sb->s_blocksize_bits),
+ head->b_blocknr << (sb->s_blocksize_bits - SECTOR_SIZE_BITS),
nr_blocks_towrite << inode->i_blkbits,
page);
@@ -3655,16 +3711,32 @@ static void sdfat_write_failed(struct address_space *mapping, loff_t to)
}
}
+static int sdfat_check_writable(struct super_block *sb)
+{
+ if (fsapi_check_bdi_valid(sb))
+ return -EIO;
+
+ if (sb->s_flags & MS_RDONLY)
+ return -EROFS;
+
+ return 0;
+}
+
static int __sdfat_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned int len,
unsigned int flags, struct page **pagep,
void **fsdata, get_block_t *get_block,
loff_t *bytes, const char *fname)
{
+ struct super_block *sb = mapping->host->i_sb;
int ret;
__cancel_dfr_work(mapping->host, pos, (loff_t)(pos + len), fname);
+ ret = sdfat_check_writable(sb);
+ if (unlikely(ret < 0))
+ return ret;
+
*pagep = NULL;
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
get_block, bytes);
@@ -3719,7 +3791,7 @@ static int sdfat_write_end(struct file *file, struct address_space *mapping,
sdfat_write_failed(mapping, pos+len);
if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) {
- inode->i_mtime = inode->i_ctime = current_time(inode);
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
fid->attr |= ATTR_ARCHIVE;
mark_inode_dirty(inode);
}
@@ -4725,9 +4797,12 @@ 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 ts;
FS_INFO_T *fsi = &(sbi->fsi);
DIR_ENTRY_T info;
+ ts = CURRENT_TIME_SEC;
+
SDFAT_I(inode)->fid.dir.dir = fsi->root_dir;
SDFAT_I(inode)->fid.dir.flags = 0x01;
SDFAT_I(inode)->fid.entry = -1;
@@ -4763,7 +4838,7 @@ static int sdfat_read_root(struct inode *inode)
SDFAT_I(inode)->i_size_ondisk = i_size_read(inode);
sdfat_save_attr(inode, ATTR_SUBDIR);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
set_nlink(inode, info.NumSubdirs + 2);
return 0;
}
@@ -5119,6 +5194,7 @@ static void __exit exit_sdfat_fs(void)
sdfat_destroy_inodecache();
unregister_filesystem(&sdfat_fs_type);
+
#ifdef CONFIG_SDFAT_USE_FOR_EXFAT
unregister_filesystem(&exfat_fs_type);
#endif /* CONFIG_SDFAT_USE_FOR_EXFAT */
@@ -5134,3 +5210,4 @@ module_exit(exit_sdfat_fs);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("FAT/exFAT filesystem support");
MODULE_AUTHOR("Samsung Electronics Co., Ltd.");
+
diff --git a/fs/sdfat/sdfat.h b/fs/sdfat/sdfat.h
index 6f764210f..5ac46598a 100644
--- a/fs/sdfat/sdfat.h
+++ b/fs/sdfat/sdfat.h
@@ -127,7 +127,7 @@ struct sdfat_mount_options {
unsigned char errors; /* on error: continue, panic, remount-ro */
unsigned char discard; /* flag on if -o dicard specified and device support discard() */
unsigned char fs_type; /* fs_type that user specified */
- unsigned short adj_req; /* support aligned mpage write */
+ unsigned short adj_req; /* support aligned mpage write */
};
#define SDFAT_HASH_BITS 8
@@ -301,6 +301,7 @@ static inline void sdfat_save_attr(struct inode *inode, u32 attr)
extern int sdfat_statistics_init(struct kset *sdfat_kset);
extern void sdfat_statistics_uninit(void);
extern void sdfat_statistics_set_mnt(FS_INFO_T *fsi);
+extern void sdfat_statistics_set_mnt_ro(void);
extern void sdfat_statistics_set_mkdir(u8 flags);
extern void sdfat_statistics_set_create(u8 flags);
extern void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create);
@@ -313,6 +314,7 @@ static inline int sdfat_statistics_init(struct kset *sdfat_kset)
}
static inline void sdfat_statistics_uninit(void) {};
static inline void sdfat_statistics_set_mnt(FS_INFO_T *fsi) {};
+static inline void sdfat_statistics_set_mnt_ro(void) {};
static inline void sdfat_statistics_set_mkdir(u8 flags) {};
static inline void sdfat_statistics_set_create(u8 flags) {};
static inline void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) {};
diff --git a/fs/sdfat/sdfat_fs.h b/fs/sdfat/sdfat_fs.h
index 998ca84c9..487ac3f8a 100644
--- a/fs/sdfat/sdfat_fs.h
+++ b/fs/sdfat/sdfat_fs.h
@@ -68,6 +68,8 @@
#define MAX_NAME_LENGTH 255 // max len of file name excluding NULL
#define DOS_NAME_LENGTH 11 // DOS file name length excluding NULL
+#define SECTOR_SIZE_BITS 9 /* VFS sector size is 512 bytes */
+
#define DENTRY_SIZE 32 /* directory entry size */
#define DENTRY_SIZE_BITS 5
diff --git a/fs/sdfat/statistics.c b/fs/sdfat/statistics.c
index 2ae1a93fb..099d9a358 100644
--- a/fs/sdfat/statistics.c
+++ b/fs/sdfat/statistics.c
@@ -8,6 +8,7 @@ enum {
SDFAT_MNT_FAT16,
SDFAT_MNT_FAT32,
SDFAT_MNT_EXFAT,
+ SDFAT_MNT_RO,
SDFAT_MNT_MAX
};
@@ -85,11 +86,12 @@ static ssize_t mount_show(struct kobject *kobj,
{
return snprintf(buff, PAGE_SIZE, "\"FAT12_MNT_I\":\"%u\","
"\"FAT16_MNT_I\":\"%u\",\"FAT32_MNT_I\":\"%u\","
- "\"EXFAT_MNT_I\":\"%u\"\n",
+ "\"EXFAT_MNT_I\":\"%u\",\"RO_MNT_I\":\"%u\"\n",
statistics.mnt_cnt[SDFAT_MNT_FAT12],
statistics.mnt_cnt[SDFAT_MNT_FAT16],
statistics.mnt_cnt[SDFAT_MNT_FAT32],
- statistics.mnt_cnt[SDFAT_MNT_EXFAT]);
+ statistics.mnt_cnt[SDFAT_MNT_EXFAT],
+ statistics.mnt_cnt[SDFAT_MNT_RO]);
}
static ssize_t nofat_op_show(struct kobject *kobj,
@@ -201,6 +203,11 @@ void sdfat_statistics_set_mnt(FS_INFO_T *fsi)
statistics.clus_vfat[SDFAT_VF_CLUS_MAX - 1]++;
}
+void sdfat_statistics_set_mnt_ro(void)
+{
+ statistics.mnt_cnt[SDFAT_MNT_RO]++;
+}
+
void sdfat_statistics_set_mkdir(u8 flags)
{
if (flags != 0x03)
diff --git a/fs/sdfat/version.h b/fs/sdfat/version.h
index 999f052a7..3cd0b7369 100644
--- a/fs/sdfat/version.h
+++ b/fs/sdfat/version.h
@@ -22,4 +22,4 @@
/* PURPOSE : sdFAT File Manager */
/* */
/************************************************************************/
-#define SDFAT_VERSION "2.0.8-lineage"
+#define SDFAT_VERSION "2.1.8-lineage"