mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 07:03:09 -04:00
commit
74685118bd
9 changed files with 131 additions and 178 deletions
11
cache.c
11
cache.c
|
|
@ -17,7 +17,6 @@
|
|||
#include "exfat_raw.h"
|
||||
#include "exfat_fs.h"
|
||||
|
||||
#define EXFAT_CACHE_VALID 0
|
||||
#define EXFAT_MAX_CACHE 16
|
||||
|
||||
struct exfat_cache {
|
||||
|
|
@ -61,16 +60,6 @@ void exfat_cache_shutdown(void)
|
|||
kmem_cache_destroy(exfat_cachep);
|
||||
}
|
||||
|
||||
void exfat_cache_init_inode(struct inode *inode)
|
||||
{
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
|
||||
spin_lock_init(&ei->cache_lru_lock);
|
||||
ei->nr_caches = 0;
|
||||
ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
|
||||
INIT_LIST_HEAD(&ei->cache_lru);
|
||||
}
|
||||
|
||||
static inline struct exfat_cache *exfat_cache_alloc(void)
|
||||
{
|
||||
return kmem_cache_alloc(exfat_cachep, GFP_NOFS);
|
||||
|
|
|
|||
29
dir.c
29
dir.c
|
|
@ -60,9 +60,9 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
|
|||
}
|
||||
|
||||
/* read a directory entry from the opened directory */
|
||||
static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry)
|
||||
static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
|
||||
{
|
||||
int i, dentries_per_clu, dentries_per_clu_bits = 0;
|
||||
int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext;
|
||||
unsigned int type, clu_offset;
|
||||
sector_t sector;
|
||||
struct exfat_chain dir, clu;
|
||||
|
|
@ -71,7 +71,7 @@ static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry)
|
|||
struct super_block *sb = inode->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
unsigned int dentry = ei->rwoffset & 0xFFFFFFFF;
|
||||
unsigned int dentry = EXFAT_B_TO_DEN(*cpos) & 0xFFFFFFFF;
|
||||
struct buffer_head *bh;
|
||||
|
||||
/* check if the given file ID is opened */
|
||||
|
|
@ -128,6 +128,7 @@ static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry)
|
|||
continue;
|
||||
}
|
||||
|
||||
num_ext = ep->dentry.file.num_ext;
|
||||
dir_entry->attr = le16_to_cpu(ep->dentry.file.attr);
|
||||
exfat_get_entry_time(sbi, &dir_entry->crtime,
|
||||
ep->dentry.file.create_tz,
|
||||
|
|
@ -158,12 +159,13 @@ static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry)
|
|||
return -EIO;
|
||||
dir_entry->size =
|
||||
le64_to_cpu(ep->dentry.stream.valid_size);
|
||||
dir_entry->entry = dentry;
|
||||
brelse(bh);
|
||||
|
||||
ei->hint_bmap.off = dentry >> dentries_per_clu_bits;
|
||||
ei->hint_bmap.clu = clu.dir;
|
||||
|
||||
ei->rwoffset = ++dentry;
|
||||
*cpos = EXFAT_DEN_TO_B(dentry + 1 + num_ext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -179,7 +181,7 @@ static int exfat_readdir(struct inode *inode, struct exfat_dir_entry *dir_entry)
|
|||
}
|
||||
|
||||
dir_entry->namebuf.lfn[0] = '\0';
|
||||
ei->rwoffset = dentry;
|
||||
*cpos = EXFAT_DEN_TO_B(dentry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -243,12 +245,10 @@ static int exfat_iterate(struct file *filp, struct dir_context *ctx)
|
|||
if (err)
|
||||
goto unlock;
|
||||
get_new:
|
||||
ei->rwoffset = EXFAT_B_TO_DEN(cpos);
|
||||
|
||||
if (cpos >= i_size_read(inode))
|
||||
goto end_of_dir;
|
||||
|
||||
err = exfat_readdir(inode, &de);
|
||||
err = exfat_readdir(inode, &cpos, &de);
|
||||
if (err) {
|
||||
/*
|
||||
* At least we tried to read a sector. Move cpos to next sector
|
||||
|
|
@ -263,13 +263,10 @@ get_new:
|
|||
goto end_of_dir;
|
||||
}
|
||||
|
||||
cpos = EXFAT_DEN_TO_B(ei->rwoffset);
|
||||
|
||||
if (!nb->lfn[0])
|
||||
goto end_of_dir;
|
||||
|
||||
i_pos = ((loff_t)ei->start_clu << 32) |
|
||||
((ei->rwoffset - 1) & 0xffffffff);
|
||||
i_pos = ((loff_t)ei->start_clu << 32) | (de.entry & 0xffffffff);
|
||||
tmp = exfat_iget(sb, i_pos);
|
||||
if (tmp) {
|
||||
inum = tmp->i_ino;
|
||||
|
|
@ -922,7 +919,6 @@ enum {
|
|||
/*
|
||||
* return values:
|
||||
* >= 0 : return dir entiry position with the name in dir
|
||||
* -EEXIST : (root dir, ".") it is the root dir itself
|
||||
* -ENOENT : entry with the name does not exist
|
||||
* -EIO : I/O error
|
||||
*/
|
||||
|
|
@ -990,11 +986,8 @@ rewind:
|
|||
if (ei->hint_femp.eidx ==
|
||||
EXFAT_HINT_NONE ||
|
||||
candi_empty.eidx <=
|
||||
ei->hint_femp.eidx) {
|
||||
memcpy(&ei->hint_femp,
|
||||
&candi_empty,
|
||||
sizeof(candi_empty));
|
||||
}
|
||||
ei->hint_femp.eidx)
|
||||
ei->hint_femp = candi_empty;
|
||||
}
|
||||
|
||||
brelse(bh);
|
||||
|
|
|
|||
15
exfat_fs.h
15
exfat_fs.h
|
|
@ -11,7 +11,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include <linux/nls.h>
|
||||
|
||||
#define EXFAT_VERSION "5.8.7"
|
||||
#define EXFAT_VERSION "5.10.1"
|
||||
|
||||
#define EXFAT_SUPER_MAGIC 0x2011BAB0UL
|
||||
#define EXFAT_ROOT_INO 1
|
||||
|
|
@ -131,7 +131,7 @@ enum {
|
|||
|
||||
struct exfat_dentry_namebuf {
|
||||
char *lfn;
|
||||
int lfnbuf_len; /* usally MAX_UNINAME_BUF_SIZE */
|
||||
int lfnbuf_len; /* usually MAX_UNINAME_BUF_SIZE */
|
||||
};
|
||||
|
||||
/* unicode name structure */
|
||||
|
|
@ -233,7 +233,8 @@ struct exfat_sb_info {
|
|||
unsigned int num_FAT_sectors; /* num of FAT sectors */
|
||||
unsigned int root_dir; /* root dir cluster */
|
||||
unsigned int dentries_per_clu; /* num of dentries per cluster */
|
||||
unsigned int vol_flag; /* volume dirty flag */
|
||||
unsigned int vol_flags; /* volume flags */
|
||||
unsigned int vol_flags_persistent; /* volume flags to retain */
|
||||
struct buffer_head *boot_bh; /* buffer_head of BOOT sector */
|
||||
|
||||
unsigned int map_clu; /* allocation bitmap start cluster */
|
||||
|
|
@ -256,6 +257,8 @@ struct exfat_sb_info {
|
|||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
#define EXFAT_CACHE_VALID 0
|
||||
|
||||
/*
|
||||
* EXFAT file system inode in-memory data
|
||||
*/
|
||||
|
|
@ -271,8 +274,6 @@ struct exfat_inode_info {
|
|||
* the validation of hint_stat.
|
||||
*/
|
||||
unsigned int version;
|
||||
/* file offset or dentry index for readdir */
|
||||
loff_t rwoffset;
|
||||
|
||||
/* hint for cluster last accessed */
|
||||
struct exfat_hint hint_bmap;
|
||||
|
|
@ -393,7 +394,8 @@ static inline int exfat_sector_to_cluster(struct exfat_sb_info *sbi,
|
|||
}
|
||||
|
||||
/* super.c */
|
||||
int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag);
|
||||
int exfat_set_volume_dirty(struct super_block *sb);
|
||||
int exfat_clear_volume_dirty(struct super_block *sb);
|
||||
|
||||
/* fatent.c */
|
||||
#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu)
|
||||
|
|
@ -445,7 +447,6 @@ extern const struct dentry_operations exfat_utf8_dentry_ops;
|
|||
/* cache.c */
|
||||
int exfat_cache_init(void);
|
||||
void exfat_cache_shutdown(void);
|
||||
void exfat_cache_init_inode(struct inode *inode);
|
||||
void exfat_cache_inval_inode(struct inode *inode);
|
||||
int exfat_get_cluster(struct inode *inode, unsigned int cluster,
|
||||
unsigned int *fclus, unsigned int *dclus,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@
|
|||
|
||||
#define EXFAT_MAX_FILE_LEN 255
|
||||
|
||||
#define VOL_CLEAN 0x0000
|
||||
#define VOL_DIRTY 0x0002
|
||||
#define ERR_MEDIUM 0x0004
|
||||
#define VOLUME_DIRTY 0x0002
|
||||
#define MEDIA_FAILURE 0x0004
|
||||
|
||||
#define EXFAT_EOF_CLUSTER 0xFFFFFFFFu
|
||||
#define EXFAT_BAD_CLUSTER 0xFFFFFFF7u
|
||||
|
|
|
|||
8
file.c
8
file.c
|
|
@ -115,7 +115,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
|||
if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
|
||||
return -EPERM;
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
|
||||
num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi);
|
||||
num_clusters_phys =
|
||||
|
|
@ -225,8 +225,6 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
|||
/* hint information */
|
||||
ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
|
||||
ei->hint_bmap.clu = EXFAT_EOF_CLUSTER;
|
||||
if (ei->rwoffset > new_size)
|
||||
ei->rwoffset = new_size;
|
||||
|
||||
/* hint_stat will be used if this is directory. */
|
||||
ei->hint_stat.eidx = 0;
|
||||
|
|
@ -237,7 +235,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
|||
if (exfat_free_cluster(inode, &clu))
|
||||
return -EIO;
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -246,7 +244,7 @@ void exfat_truncate(struct inode *inode, loff_t size)
|
|||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
unsigned int blocksize = 1 << inode->i_blkbits;
|
||||
unsigned int blocksize = i_blocksize(inode);
|
||||
loff_t aligned_size;
|
||||
int err;
|
||||
|
||||
|
|
|
|||
11
inode.c
11
inode.c
|
|
@ -41,7 +41,7 @@ static int __exfat_write_inode(struct inode *inode, int sync)
|
|||
if (is_dir && ei->dir.dir == sbi->root_dir && ei->entry == -1)
|
||||
return 0;
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
|
||||
/* get the directory entry of given file or directory */
|
||||
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES);
|
||||
|
|
@ -116,8 +116,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
|||
unsigned int local_clu_offset = clu_offset;
|
||||
unsigned int num_to_be_allocated = 0, num_clusters = 0;
|
||||
|
||||
ei->rwoffset = EXFAT_CLU_TO_B(clu_offset, sbi);
|
||||
|
||||
if (EXFAT_I(inode)->i_size_ondisk > 0)
|
||||
num_clusters =
|
||||
EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk,
|
||||
|
|
@ -169,7 +167,7 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
|||
}
|
||||
|
||||
if (*clu == EXFAT_EOF_CLUSTER) {
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
|
||||
new_clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
|
||||
EXFAT_EOF_CLUSTER : last_clu + 1;
|
||||
|
|
@ -584,7 +582,7 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
|
|||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
loff_t size = info->size;
|
||||
|
||||
memcpy(&ei->dir, &info->dir, sizeof(struct exfat_chain));
|
||||
ei->dir = info->dir;
|
||||
ei->entry = info->entry;
|
||||
ei->attr = info->attr;
|
||||
ei->start_clu = info->start_clu;
|
||||
|
|
@ -595,7 +593,6 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
|
|||
ei->hint_stat.eidx = 0;
|
||||
ei->hint_stat.clu = info->start_clu;
|
||||
ei->hint_femp.eidx = EXFAT_HINT_NONE;
|
||||
ei->rwoffset = 0;
|
||||
ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
|
||||
ei->i_pos = 0;
|
||||
|
||||
|
|
@ -643,8 +640,6 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
|
|||
ei->i_crtime = info->crtime;
|
||||
inode->i_atime = info->atime;
|
||||
|
||||
exfat_cache_init_inode(inode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
184
namei.c
184
namei.c
|
|
@ -317,7 +317,7 @@ static int exfat_check_max_dentries(struct inode *inode)
|
|||
{
|
||||
if (EXFAT_B_TO_DEN(i_size_read(inode)) >= MAX_EXFAT_DENTRIES) {
|
||||
/*
|
||||
* exFAT spec allows a dir to grow upto 8388608(256MB)
|
||||
* exFAT spec allows a dir to grow up to 8388608(256MB)
|
||||
* dentries
|
||||
*/
|
||||
return -ENOSPC;
|
||||
|
|
@ -345,8 +345,7 @@ static int exfat_find_empty_entry(struct inode *inode,
|
|||
hint_femp.eidx = EXFAT_HINT_NONE;
|
||||
|
||||
if (ei->hint_femp.eidx != EXFAT_HINT_NONE) {
|
||||
memcpy(&hint_femp, &ei->hint_femp,
|
||||
sizeof(struct exfat_hint_femp));
|
||||
hint_femp = ei->hint_femp;
|
||||
ei->hint_femp.eidx = EXFAT_HINT_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -546,7 +545,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
memcpy(&info->dir, p_dir, sizeof(struct exfat_chain));
|
||||
info->dir = *p_dir;
|
||||
info->entry = dentry;
|
||||
info->flags = ALLOC_NO_FAT_CHAIN;
|
||||
info->type = type;
|
||||
|
|
@ -557,19 +556,10 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||
info->size = 0;
|
||||
info->num_subdirs = 0;
|
||||
} else {
|
||||
int count;
|
||||
struct exfat_chain cdir;
|
||||
|
||||
info->attr = ATTR_SUBDIR;
|
||||
info->start_clu = start_clu;
|
||||
info->size = clu_size;
|
||||
|
||||
exfat_chain_set(&cdir, info->start_clu,
|
||||
EXFAT_B_TO_CLU(info->size, sbi), info->flags);
|
||||
count = exfat_count_dir_entries(sb, &cdir);
|
||||
if (count < 0)
|
||||
return -EIO;
|
||||
info->num_subdirs = count + EXFAT_MIN_SUBDIR;
|
||||
info->num_subdirs = EXFAT_MIN_SUBDIR;
|
||||
}
|
||||
memset(&info->crtime, 0, sizeof(info->crtime));
|
||||
memset(&info->mtime, 0, sizeof(info->mtime));
|
||||
|
|
@ -589,10 +579,10 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
int err;
|
||||
|
||||
mutex_lock(&EXFAT_SB(sb)->s_lock);
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
|
||||
&info);
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
|
|
@ -613,7 +603,8 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
|
|||
|
||||
i_pos = exfat_make_i_pos(&info);
|
||||
inode = exfat_build_inode(sb, &info, i_pos);
|
||||
if (IS_ERR(inode))
|
||||
err = PTR_ERR_OR_ZERO(inode);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||
|
|
@ -648,6 +639,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
|
|||
struct super_block *sb = dir->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct exfat_inode_info *ei = EXFAT_I(dir);
|
||||
struct exfat_dentry *ep, *ep2;
|
||||
struct exfat_entry_set_cache *es;
|
||||
|
||||
if (qname->len == 0)
|
||||
return -ENOENT;
|
||||
|
|
@ -681,91 +674,63 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
|
|||
dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name,
|
||||
num_entries, TYPE_ALL);
|
||||
|
||||
if ((dentry < 0) && (dentry != -EEXIST))
|
||||
if (dentry < 0)
|
||||
return dentry; /* -error value */
|
||||
|
||||
memcpy(&info->dir, &cdir.dir, sizeof(struct exfat_chain));
|
||||
info->dir = cdir;
|
||||
info->entry = dentry;
|
||||
info->num_subdirs = 0;
|
||||
|
||||
/* root directory itself */
|
||||
if (unlikely(dentry == -EEXIST)) {
|
||||
int num_clu = 0;
|
||||
es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
|
||||
if (!es)
|
||||
return -EIO;
|
||||
ep = exfat_get_dentry_cached(es, 0);
|
||||
ep2 = exfat_get_dentry_cached(es, 1);
|
||||
|
||||
info->type = TYPE_DIR;
|
||||
info->attr = ATTR_SUBDIR;
|
||||
info->flags = ALLOC_FAT_CHAIN;
|
||||
info->start_clu = sbi->root_dir;
|
||||
memset(&info->crtime, 0, sizeof(info->crtime));
|
||||
memset(&info->mtime, 0, sizeof(info->mtime));
|
||||
memset(&info->atime, 0, sizeof(info->atime));
|
||||
info->type = exfat_get_entry_type(ep);
|
||||
info->attr = le16_to_cpu(ep->dentry.file.attr);
|
||||
info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
|
||||
if ((info->type == TYPE_FILE) && (info->size == 0)) {
|
||||
info->flags = ALLOC_NO_FAT_CHAIN;
|
||||
info->start_clu = EXFAT_EOF_CLUSTER;
|
||||
} else {
|
||||
info->flags = ep2->dentry.stream.flags;
|
||||
info->start_clu =
|
||||
le32_to_cpu(ep2->dentry.stream.start_clu);
|
||||
}
|
||||
|
||||
exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
|
||||
if (exfat_count_num_clusters(sb, &cdir, &num_clu))
|
||||
return -EIO;
|
||||
info->size = num_clu << sbi->cluster_size_bits;
|
||||
exfat_get_entry_time(sbi, &info->crtime,
|
||||
ep->dentry.file.create_tz,
|
||||
ep->dentry.file.create_time,
|
||||
ep->dentry.file.create_date,
|
||||
ep->dentry.file.create_time_cs);
|
||||
exfat_get_entry_time(sbi, &info->mtime,
|
||||
ep->dentry.file.modify_tz,
|
||||
ep->dentry.file.modify_time,
|
||||
ep->dentry.file.modify_date,
|
||||
ep->dentry.file.modify_time_cs);
|
||||
exfat_get_entry_time(sbi, &info->atime,
|
||||
ep->dentry.file.access_tz,
|
||||
ep->dentry.file.access_time,
|
||||
ep->dentry.file.access_date,
|
||||
0);
|
||||
exfat_free_dentry_set(es, false);
|
||||
|
||||
if (ei->start_clu == EXFAT_FREE_CLUSTER) {
|
||||
exfat_fs_error(sb,
|
||||
"non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)",
|
||||
i_size_read(dir), ei->dir.dir, ei->entry);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (info->type == TYPE_DIR) {
|
||||
exfat_chain_set(&cdir, info->start_clu,
|
||||
EXFAT_B_TO_CLU(info->size, sbi), info->flags);
|
||||
count = exfat_count_dir_entries(sb, &cdir);
|
||||
if (count < 0)
|
||||
return -EIO;
|
||||
|
||||
info->num_subdirs = count;
|
||||
} else {
|
||||
struct exfat_dentry *ep, *ep2;
|
||||
struct exfat_entry_set_cache *es;
|
||||
|
||||
es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
|
||||
if (!es)
|
||||
return -EIO;
|
||||
ep = exfat_get_dentry_cached(es, 0);
|
||||
ep2 = exfat_get_dentry_cached(es, 1);
|
||||
|
||||
info->type = exfat_get_entry_type(ep);
|
||||
info->attr = le16_to_cpu(ep->dentry.file.attr);
|
||||
info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
|
||||
if ((info->type == TYPE_FILE) && (info->size == 0)) {
|
||||
info->flags = ALLOC_NO_FAT_CHAIN;
|
||||
info->start_clu = EXFAT_EOF_CLUSTER;
|
||||
} else {
|
||||
info->flags = ep2->dentry.stream.flags;
|
||||
info->start_clu =
|
||||
le32_to_cpu(ep2->dentry.stream.start_clu);
|
||||
}
|
||||
|
||||
if (ei->start_clu == EXFAT_FREE_CLUSTER) {
|
||||
exfat_fs_error(sb,
|
||||
"non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)",
|
||||
i_size_read(dir), ei->dir.dir, ei->entry);
|
||||
exfat_free_dentry_set(es, false);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
exfat_get_entry_time(sbi, &info->crtime,
|
||||
ep->dentry.file.create_tz,
|
||||
ep->dentry.file.create_time,
|
||||
ep->dentry.file.create_date,
|
||||
ep->dentry.file.create_time_cs);
|
||||
exfat_get_entry_time(sbi, &info->mtime,
|
||||
ep->dentry.file.modify_tz,
|
||||
ep->dentry.file.modify_time,
|
||||
ep->dentry.file.modify_date,
|
||||
ep->dentry.file.modify_time_cs);
|
||||
exfat_get_entry_time(sbi, &info->atime,
|
||||
ep->dentry.file.access_tz,
|
||||
ep->dentry.file.access_time,
|
||||
ep->dentry.file.access_date,
|
||||
0);
|
||||
exfat_free_dentry_set(es, false);
|
||||
|
||||
if (info->type == TYPE_DIR) {
|
||||
exfat_chain_set(&cdir, info->start_clu,
|
||||
EXFAT_B_TO_CLU(info->size, sbi), info->flags);
|
||||
count = exfat_count_dir_entries(sb, &cdir);
|
||||
if (count < 0)
|
||||
return -EIO;
|
||||
|
||||
info->num_subdirs = count + EXFAT_MIN_SUBDIR;
|
||||
}
|
||||
info->num_subdirs = count + EXFAT_MIN_SUBDIR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -798,10 +763,9 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
i_pos = exfat_make_i_pos(&info);
|
||||
inode = exfat_build_inode(sb, &info, i_pos);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
err = PTR_ERR_OR_ZERO(inode);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
i_mode = inode->i_mode;
|
||||
alias = d_find_alias(inode);
|
||||
|
|
@ -891,7 +855,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
|||
num_entries++;
|
||||
brelse(bh);
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
/* update the directory entry */
|
||||
if (exfat_remove_entries(dir, &cdir, entry, 0, num_entries)) {
|
||||
err = -EIO;
|
||||
|
|
@ -900,7 +864,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
|||
|
||||
/* This doesn't modify ei */
|
||||
ei->dir.dir = DIR_DELETED;
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||
inode_inc_iversion(dir);
|
||||
|
|
@ -946,10 +910,10 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
int err;
|
||||
|
||||
mutex_lock(&EXFAT_SB(sb)->s_lock);
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
|
||||
&info);
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
|
|
@ -972,10 +936,9 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
|
||||
i_pos = exfat_make_i_pos(&info);
|
||||
inode = exfat_build_inode(sb, &info, i_pos);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
err = PTR_ERR_OR_ZERO(inode);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||
inode_inc_iversion(inode);
|
||||
|
|
@ -1092,14 +1055,14 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
num_entries++;
|
||||
brelse(bh);
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries);
|
||||
if (err) {
|
||||
exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err);
|
||||
goto unlock;
|
||||
}
|
||||
ei->dir.dir = DIR_DELETED;
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
|
||||
inode_inc_iversion(dir);
|
||||
|
|
@ -1173,7 +1136,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
|
|||
if (!epnew)
|
||||
return -EIO;
|
||||
|
||||
memcpy(epnew, epold, DENTRY_SIZE);
|
||||
*epnew = *epold;
|
||||
if (exfat_get_entry_type(epnew) == TYPE_FILE) {
|
||||
epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE);
|
||||
ei->attr |= ATTR_ARCHIVE;
|
||||
|
|
@ -1193,7 +1156,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(epnew, epold, DENTRY_SIZE);
|
||||
*epnew = *epold;
|
||||
exfat_update_bh(new_bh, sync);
|
||||
brelse(old_bh);
|
||||
brelse(new_bh);
|
||||
|
|
@ -1238,11 +1201,6 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
|
|||
if (!epmov)
|
||||
return -EIO;
|
||||
|
||||
/* check if the source and target directory is the same */
|
||||
if (exfat_get_entry_type(epmov) == TYPE_DIR &&
|
||||
le32_to_cpu(epmov->dentry.stream.start_clu) == p_newdir->dir)
|
||||
return -EINVAL;
|
||||
|
||||
num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry,
|
||||
epmov);
|
||||
if (num_old_entries < 0)
|
||||
|
|
@ -1261,7 +1219,7 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
|
|||
if (!epnew)
|
||||
return -EIO;
|
||||
|
||||
memcpy(epnew, epmov, DENTRY_SIZE);
|
||||
*epnew = *epmov;
|
||||
if (exfat_get_entry_type(epnew) == TYPE_FILE) {
|
||||
epnew->dentry.file.attr |= cpu_to_le16(ATTR_ARCHIVE);
|
||||
ei->attr |= ATTR_ARCHIVE;
|
||||
|
|
@ -1281,7 +1239,7 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(epnew, epmov, DENTRY_SIZE);
|
||||
*epnew = *epmov;
|
||||
exfat_update_bh(new_bh, IS_DIRSYNC(inode));
|
||||
brelse(mov_bh);
|
||||
brelse(new_bh);
|
||||
|
|
@ -1407,7 +1365,7 @@ static int __exfat_rename(struct inode *old_parent_inode,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_set_volume_dirty(sb);
|
||||
|
||||
if (olddir.dir == newdir.dir)
|
||||
ret = exfat_rename_file(new_parent_inode, &olddir, dentry,
|
||||
|
|
@ -1462,7 +1420,7 @@ del_out:
|
|||
*/
|
||||
new_ei->dir.dir = DIR_DELETED;
|
||||
}
|
||||
exfat_set_vol_flags(sb, VOL_CLEAN);
|
||||
exfat_clear_volume_dirty(sb);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
2
nls.c
2
nls.c
|
|
@ -11,7 +11,7 @@
|
|||
#include "exfat_raw.h"
|
||||
#include "exfat_fs.h"
|
||||
|
||||
/* Upcase tabel macro */
|
||||
/* Upcase table macro */
|
||||
#define EXFAT_NUM_UPCASE (2918)
|
||||
#define UTBL_COUNT (0x10000)
|
||||
|
||||
|
|
|
|||
42
super.c
42
super.c
|
|
@ -76,7 +76,7 @@ static int exfat_sync_fs(struct super_block *sb, int wait)
|
|||
/* If there are some dirty buffers in the bdev inode */
|
||||
mutex_lock(&sbi->s_lock);
|
||||
sync_blockdev(sb->s_bdev);
|
||||
if (exfat_set_vol_flags(sb, VOL_CLEAN))
|
||||
if (exfat_clear_volume_dirty(sb))
|
||||
err = -EIO;
|
||||
mutex_unlock(&sbi->s_lock);
|
||||
return err;
|
||||
|
|
@ -109,17 +109,20 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
|
||||
static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)
|
||||
{
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
|
||||
bool sync;
|
||||
|
||||
/* retain persistent-flags */
|
||||
new_flags |= sbi->vol_flags_persistent;
|
||||
|
||||
/* flags are not changed */
|
||||
if (sbi->vol_flag == new_flag)
|
||||
if (sbi->vol_flags == new_flags)
|
||||
return 0;
|
||||
|
||||
sbi->vol_flag = new_flag;
|
||||
sbi->vol_flags = new_flags;
|
||||
|
||||
/* skip updating volume dirty flag,
|
||||
* if this volume has been mounted with read-only
|
||||
|
|
@ -131,9 +134,9 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
|
|||
#endif
|
||||
return 0;
|
||||
|
||||
p_boot->vol_flags = cpu_to_le16(new_flag);
|
||||
p_boot->vol_flags = cpu_to_le16(new_flags);
|
||||
|
||||
if (new_flag == VOL_DIRTY && !buffer_dirty(sbi->boot_bh))
|
||||
if ((new_flags & VOLUME_DIRTY) && !buffer_dirty(sbi->boot_bh))
|
||||
sync = true;
|
||||
else
|
||||
sync = false;
|
||||
|
|
@ -146,6 +149,20 @@ int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flag)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int exfat_set_volume_dirty(struct super_block *sb)
|
||||
{
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
|
||||
return exfat_set_vol_flags(sb, sbi->vol_flags | VOLUME_DIRTY);
|
||||
}
|
||||
|
||||
int exfat_clear_volume_dirty(struct super_block *sb)
|
||||
{
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
|
||||
return exfat_set_vol_flags(sb, sbi->vol_flags & ~VOLUME_DIRTY);
|
||||
}
|
||||
|
||||
static int exfat_show_options(struct seq_file *m, struct dentry *root)
|
||||
{
|
||||
struct super_block *sb = root->d_sb;
|
||||
|
|
@ -560,7 +577,6 @@ static int exfat_read_root(struct inode *inode)
|
|||
ei->flags = ALLOC_FAT_CHAIN;
|
||||
ei->type = TYPE_DIR;
|
||||
ei->version = 0;
|
||||
ei->rwoffset = 0;
|
||||
ei->hint_bmap.off = EXFAT_EOF_CLUSTER;
|
||||
ei->hint_stat.eidx = 0;
|
||||
ei->hint_stat.clu = sbi->root_dir;
|
||||
|
|
@ -604,7 +620,6 @@ static int exfat_read_root(struct inode *inode)
|
|||
CURRENT_TIME_SEC;
|
||||
#endif
|
||||
exfat_truncate_atime(&inode->i_atime);
|
||||
exfat_cache_init_inode(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -702,7 +717,8 @@ static int exfat_read_boot_sector(struct super_block *sb)
|
|||
sbi->dentries_per_clu = 1 <<
|
||||
(sbi->cluster_size_bits - DENTRY_SIZE_BITS);
|
||||
|
||||
sbi->vol_flag = le16_to_cpu(p_boot->vol_flags);
|
||||
sbi->vol_flags = le16_to_cpu(p_boot->vol_flags);
|
||||
sbi->vol_flags_persistent = sbi->vol_flags & (VOLUME_DIRTY | MEDIA_FAILURE);
|
||||
sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
|
||||
sbi->used_clusters = EXFAT_CLUSTERS_UNTRACKED;
|
||||
|
||||
|
|
@ -717,9 +733,9 @@ static int exfat_read_boot_sector(struct super_block *sb)
|
|||
exfat_err(sb, "bogus data start sector");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sbi->vol_flag & VOL_DIRTY)
|
||||
if (sbi->vol_flags & VOLUME_DIRTY)
|
||||
exfat_warn(sb, "Volume was not properly unmounted. Some data may be corrupt. Please run fsck.");
|
||||
if (sbi->vol_flag & ERR_MEDIUM)
|
||||
if (sbi->vol_flags & MEDIA_FAILURE)
|
||||
exfat_warn(sb, "Medium has reported failures. Some data may be lost.");
|
||||
|
||||
/* exFAT file size is limited by a disk volume size */
|
||||
|
|
@ -1045,6 +1061,10 @@ static void exfat_inode_init_once(void *foo)
|
|||
{
|
||||
struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
|
||||
|
||||
spin_lock_init(&ei->cache_lru_lock);
|
||||
ei->nr_caches = 0;
|
||||
ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
|
||||
INIT_LIST_HEAD(&ei->cache_lru);
|
||||
INIT_HLIST_NODE(&ei->i_hash_fat);
|
||||
inode_init_once(&ei->vfs_inode);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue