Merge remote-tracking branch 'namjaejeon/linux-exfat-oot/master' into android12-base
* namjaejeon/linux-exfat-oot/master: exfat: add auto build-test and simple stability test using travis-CI exfat: Drop superfluous new line for error messages exfat: Downgrade ENAMETOOLONG error message to debug messages exfat: Expand exfat_err() and co directly to pr_*() macro exfat: Define NLS_NAME_* as bit flags explicitly exfat: Return ENAMETOOLONG consistently for oversized paths exfat: simplified by using round_up() fs: Convert mpage_readpage to mpage_read_folio fs: Remove flags parameter from aops->write_begin fs: Remove aop flags parameter from cont_write_begin() block: add a bdev_discard_granularity helper block: remove QUEUE_FLAG_DISCARD exfat: remove duplicate write inode for extending dir/file exfat: remove duplicate write inode for truncating file exfat: reuse __exfat_write_inode() to update directory entry Change-Id: I1a261613e988757b34f2b7baa1242f55845d8a9a Signed-off-by: UtsavBalar1231 <utsavbalar1231@gmail.com>
This commit is contained in:
commit
493e31873c
@ -36,9 +36,9 @@ enum exfat_error_mode {
|
||||
* exfat nls lossy flag
|
||||
*/
|
||||
enum {
|
||||
NLS_NAME_NO_LOSSY, /* no lossy */
|
||||
NLS_NAME_LOSSY, /* just detected incorrect filename(s) */
|
||||
NLS_NAME_OVERLEN, /* the length is over than its limit */
|
||||
NLS_NAME_NO_LOSSY = 0, /* no lossy */
|
||||
NLS_NAME_LOSSY = 1 << 0, /* just detected incorrect filename(s) */
|
||||
NLS_NAME_OVERLEN = 1 << 1, /* the length is over than its limit */
|
||||
};
|
||||
|
||||
#define EXFAT_HASH_BITS 8
|
||||
@ -515,6 +515,7 @@ struct inode *exfat_build_inode(struct super_block *sb,
|
||||
void exfat_hash_inode(struct inode *inode, loff_t i_pos);
|
||||
void exfat_unhash_inode(struct inode *inode);
|
||||
struct inode *exfat_iget(struct super_block *sb, loff_t i_pos);
|
||||
int __exfat_write_inode(struct inode *inode, int sync);
|
||||
int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
|
||||
void exfat_evict_inode(struct inode *inode);
|
||||
int exfat_block_truncate_page(struct inode *inode, loff_t from);
|
||||
@ -540,14 +541,16 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
|
||||
#define exfat_fs_error_ratelimit(sb, fmt, args...) \
|
||||
__exfat_fs_error(sb, __ratelimit(&EXFAT_SB(sb)->ratelimit), \
|
||||
fmt, ## args)
|
||||
void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
|
||||
__printf(3, 4) __cold;
|
||||
|
||||
/* expand to pr_*() with prefix */
|
||||
#define exfat_err(sb, fmt, ...) \
|
||||
exfat_msg(sb, KERN_ERR, fmt, ##__VA_ARGS__)
|
||||
pr_err("exFAT-fs (%s): " fmt "\n", (sb)->s_id, ##__VA_ARGS__)
|
||||
#define exfat_warn(sb, fmt, ...) \
|
||||
exfat_msg(sb, KERN_WARNING, fmt, ##__VA_ARGS__)
|
||||
pr_warn("exFAT-fs (%s): " fmt "\n", (sb)->s_id, ##__VA_ARGS__)
|
||||
#define exfat_info(sb, fmt, ...) \
|
||||
exfat_msg(sb, KERN_INFO, fmt, ##__VA_ARGS__)
|
||||
pr_info("exFAT-fs (%s): " fmt "\n", (sb)->s_id, ##__VA_ARGS__)
|
||||
#define exfat_debug(sb, fmt, ...) \
|
||||
pr_debug("exFAT-fs (%s): " fmt "\n", (sb)->s_id, ##__VA_ARGS__)
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
|
||||
|
@ -346,7 +346,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
||||
/* find new cluster */
|
||||
if (hint_clu == EXFAT_EOF_CLUSTER) {
|
||||
if (sbi->clu_srch_ptr < EXFAT_FIRST_CLUSTER) {
|
||||
exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)\n",
|
||||
exfat_err(sb, "sbi->clu_srch_ptr is invalid (%u)",
|
||||
sbi->clu_srch_ptr);
|
||||
sbi->clu_srch_ptr = EXFAT_FIRST_CLUSTER;
|
||||
}
|
||||
|
123
fs/exfat/file.c
123
fs/exfat/file.c
@ -108,7 +108,6 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
|
||||
|
||||
/* check if the given file ID is opened */
|
||||
if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
|
||||
@ -156,58 +155,19 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
|
||||
if (ei->type == TYPE_FILE)
|
||||
ei->attr |= ATTR_ARCHIVE;
|
||||
|
||||
/* update the directory entry */
|
||||
if (!evict) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
struct timespec64 ts;
|
||||
#else
|
||||
struct timespec ts;
|
||||
#endif
|
||||
struct exfat_dentry *ep, *ep2;
|
||||
struct exfat_entry_set_cache *es;
|
||||
int err;
|
||||
|
||||
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
|
||||
ES_ALL_ENTRIES);
|
||||
if (!es)
|
||||
return -EIO;
|
||||
ep = exfat_get_dentry_cached(es, 0);
|
||||
ep2 = exfat_get_dentry_cached(es, 1);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
|
||||
ts = current_time(inode);
|
||||
#else
|
||||
ts = CURRENT_TIME_SEC;
|
||||
#endif
|
||||
exfat_set_entry_time(sbi, &ts,
|
||||
&ep->dentry.file.modify_tz,
|
||||
&ep->dentry.file.modify_time,
|
||||
&ep->dentry.file.modify_date,
|
||||
&ep->dentry.file.modify_time_cs);
|
||||
ep->dentry.file.attr = cpu_to_le16(ei->attr);
|
||||
|
||||
/* File size should be zero if there is no cluster allocated */
|
||||
if (ei->start_clu == EXFAT_EOF_CLUSTER) {
|
||||
ep2->dentry.stream.valid_size = 0;
|
||||
ep2->dentry.stream.size = 0;
|
||||
} else {
|
||||
ep2->dentry.stream.valid_size = cpu_to_le64(new_size);
|
||||
ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
|
||||
}
|
||||
|
||||
if (new_size == 0) {
|
||||
/* Any directory can not be truncated to zero */
|
||||
WARN_ON(ei->type != TYPE_FILE);
|
||||
|
||||
ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
|
||||
ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
|
||||
}
|
||||
|
||||
exfat_update_dir_chksum_with_entry_set(es);
|
||||
err = exfat_free_dentry_set(es, inode_needs_sync(inode));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* update the directory entry
|
||||
*
|
||||
* If the directory entry is updated by mark_inode_dirty(), the
|
||||
* directory entry will be written after a writeback cycle of
|
||||
* updating the bitmap/FAT, which may result in clusters being
|
||||
* freed but referenced by the directory entry in the event of a
|
||||
* sudden power failure.
|
||||
* __exfat_write_inode() is called for directory entry, bitmap
|
||||
* and FAT to be written in a same writeback.
|
||||
*/
|
||||
if (__exfat_write_inode(inode, inode_needs_sync(inode)))
|
||||
return -EIO;
|
||||
|
||||
/* cut off from the FAT chain */
|
||||
if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&
|
||||
@ -262,18 +222,8 @@ void exfat_truncate(struct inode *inode, loff_t size)
|
||||
if (err)
|
||||
goto write_size;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
|
||||
inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
#else
|
||||
inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
|
||||
#endif
|
||||
if (IS_DIRSYNC(inode))
|
||||
exfat_sync_inode(inode);
|
||||
else
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) &
|
||||
~((loff_t)sbi->cluster_size - 1)) >> inode->i_blkbits;
|
||||
inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >>
|
||||
inode->i_blkbits;
|
||||
write_size:
|
||||
aligned_size = i_size_read(inode);
|
||||
if (aligned_size & (blocksize - 1)) {
|
||||
@ -387,16 +337,12 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
attr->ia_valid &= ~ATTR_MODE;
|
||||
}
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE) {
|
||||
error = exfat_block_truncate_page(inode, attr->ia_size);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
down_write(&EXFAT_I(inode)->truncate_lock);
|
||||
truncate_setsize(inode, attr->ia_size);
|
||||
exfat_truncate(inode, attr->ia_size);
|
||||
up_write(&EXFAT_I(inode)->truncate_lock);
|
||||
}
|
||||
if (attr->ia_valid & ATTR_SIZE)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
|
||||
inode->i_mtime = inode->i_ctime = current_time(inode);
|
||||
#else
|
||||
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
|
||||
setattr_copy(&init_user_ns, inode, attr);
|
||||
@ -404,29 +350,54 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
setattr_copy(inode, attr);
|
||||
#endif
|
||||
exfat_truncate_atime(&inode->i_atime);
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE) {
|
||||
error = exfat_block_truncate_page(inode, attr->ia_size);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
down_write(&EXFAT_I(inode)->truncate_lock);
|
||||
truncate_setsize(inode, attr->ia_size);
|
||||
/*
|
||||
* __exfat_write_inode() is called from exfat_truncate(), inode
|
||||
* is already written by it, so mark_inode_dirty() is unneeded.
|
||||
*/
|
||||
exfat_truncate(inode, attr->ia_size);
|
||||
up_write(&EXFAT_I(inode)->truncate_lock);
|
||||
} else
|
||||
mark_inode_dirty(inode);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int exfat_ioctl_fitrim(struct inode *inode, unsigned long arg)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
|
||||
struct request_queue *q = bdev_get_queue(inode->i_sb->s_bdev);
|
||||
#endif
|
||||
struct fstrim_range range;
|
||||
int ret = 0;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
if (!bdev_max_discard_sectors(inode->i_sb->s_bdev))
|
||||
#else
|
||||
if (!blk_queue_discard(q))
|
||||
#endif
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range)))
|
||||
return -EFAULT;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
range.minlen = max_t(unsigned int, range.minlen,
|
||||
bdev_discard_granularity(inode->i_sb->s_bdev));
|
||||
#else
|
||||
range.minlen = max_t(unsigned int, range.minlen,
|
||||
q->limits.discard_granularity);
|
||||
#endif
|
||||
|
||||
ret = exfat_trim_fs(inode, &range);
|
||||
if (ret < 0)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "exfat_raw.h"
|
||||
#include "exfat_fs.h"
|
||||
|
||||
static int __exfat_write_inode(struct inode *inode, int sync)
|
||||
int __exfat_write_inode(struct inode *inode, int sync)
|
||||
{
|
||||
unsigned long long on_disk_size;
|
||||
struct exfat_dentry *ep, *ep2;
|
||||
@ -77,6 +77,13 @@ static int __exfat_write_inode(struct inode *inode, int sync)
|
||||
|
||||
ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);
|
||||
ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
|
||||
if (on_disk_size) {
|
||||
ep2->dentry.stream.flags = ei->flags;
|
||||
ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu);
|
||||
} else {
|
||||
ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
|
||||
ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
|
||||
}
|
||||
|
||||
exfat_update_dir_chksum_with_entry_set(es);
|
||||
return exfat_free_dentry_set(es, sync);
|
||||
@ -107,7 +114,7 @@ void exfat_sync_inode(struct inode *inode)
|
||||
static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
||||
unsigned int *clu, int create)
|
||||
{
|
||||
int ret, modified = false;
|
||||
int ret;
|
||||
unsigned int last_clu;
|
||||
struct exfat_chain new_clu;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@ -198,7 +205,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
||||
if (new_clu.flags == ALLOC_FAT_CHAIN)
|
||||
ei->flags = ALLOC_FAT_CHAIN;
|
||||
ei->start_clu = new_clu.dir;
|
||||
modified = true;
|
||||
} else {
|
||||
if (new_clu.flags != ei->flags) {
|
||||
/* no-fat-chain bit is disabled,
|
||||
@ -208,7 +214,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
||||
exfat_chain_cont_cluster(sb, ei->start_clu,
|
||||
num_clusters);
|
||||
ei->flags = ALLOC_FAT_CHAIN;
|
||||
modified = true;
|
||||
}
|
||||
if (new_clu.flags == ALLOC_FAT_CHAIN)
|
||||
if (exfat_ent_set(sb, last_clu, new_clu.dir))
|
||||
@ -218,33 +223,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
|
||||
num_clusters += num_to_be_allocated;
|
||||
*clu = new_clu.dir;
|
||||
|
||||
if (ei->dir.dir != DIR_DELETED && modified) {
|
||||
struct exfat_dentry *ep;
|
||||
struct exfat_entry_set_cache *es;
|
||||
int err;
|
||||
|
||||
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
|
||||
ES_ALL_ENTRIES);
|
||||
if (!es)
|
||||
return -EIO;
|
||||
/* get stream entry */
|
||||
ep = exfat_get_dentry_cached(es, 1);
|
||||
|
||||
/* update directory entry */
|
||||
ep->dentry.stream.flags = ei->flags;
|
||||
ep->dentry.stream.start_clu =
|
||||
cpu_to_le32(ei->start_clu);
|
||||
ep->dentry.stream.valid_size =
|
||||
cpu_to_le64(i_size_read(inode));
|
||||
ep->dentry.stream.size =
|
||||
ep->dentry.stream.valid_size;
|
||||
|
||||
exfat_update_dir_chksum_with_entry_set(es);
|
||||
err = exfat_free_dentry_set(es, inode_needs_sync(inode));
|
||||
if (err)
|
||||
return err;
|
||||
} /* end of if != DIR_DELETED */
|
||||
|
||||
inode->i_blocks +=
|
||||
num_to_be_allocated << sbi->sect_per_clus_bits;
|
||||
|
||||
@ -359,10 +337,17 @@ unlock_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
static int exfat_read_folio(struct file *file, struct folio *folio)
|
||||
{
|
||||
return mpage_read_folio(folio, exfat_get_block);
|
||||
}
|
||||
#else
|
||||
static int exfat_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
return mpage_readpage(page, exfat_get_block);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
static void exfat_readahead(struct readahead_control *rac)
|
||||
@ -394,21 +379,37 @@ static void exfat_write_failed(struct address_space *mapping, loff_t to)
|
||||
|
||||
if (to > i_size_read(inode)) {
|
||||
truncate_pagecache(inode, i_size_read(inode));
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
|
||||
inode->i_mtime = inode->i_ctime = current_time(inode);
|
||||
#else
|
||||
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
|
||||
#endif
|
||||
exfat_truncate(inode, EXFAT_I(inode)->i_size_aligned);
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
static int exfat_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len,
|
||||
struct page **pagep, void **fsdata)
|
||||
#else
|
||||
static int exfat_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int flags,
|
||||
struct page **pagep, void **fsdata)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
|
||||
*pagep = NULL;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
|
||||
exfat_get_block,
|
||||
&EXFAT_I(mapping->host)->i_size_ondisk);
|
||||
#else
|
||||
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
exfat_get_block,
|
||||
&EXFAT_I(mapping->host)->i_size_ondisk);
|
||||
|
||||
#endif
|
||||
if (ret < 0)
|
||||
exfat_write_failed(mapping, pos+len);
|
||||
|
||||
@ -522,7 +523,11 @@ static const struct address_space_operations exfat_aops = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
.read_folio = exfat_read_folio,
|
||||
#else
|
||||
.readpage = exfat_readpage,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
.readahead = exfat_readahead,
|
||||
#else
|
||||
@ -641,8 +646,8 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
|
||||
|
||||
exfat_save_attr(inode, info->attr);
|
||||
|
||||
inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) &
|
||||
~((loff_t)sbi->cluster_size - 1)) >> inode->i_blkbits;
|
||||
inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >>
|
||||
inode->i_blkbits;
|
||||
inode->i_mtime = info->mtime;
|
||||
inode->i_ctime = info->mtime;
|
||||
ei->i_crtime = info->crtime;
|
||||
|
@ -52,23 +52,6 @@ void __exfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* exfat_msg() - print preformated EXFAT specific messages.
|
||||
* All logs except what uses exfat_fs_error() should be written by exfat_msg()
|
||||
*/
|
||||
void exfat_msg(struct super_block *sb, const char *level, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
/* level means KERN_ pacility level */
|
||||
printk("%sexFAT-fs (%s): %pV\n", level, sb->s_id, &vaf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define SECS_PER_MIN (60)
|
||||
#define TIMEZONE_SEC(x) ((x) * 15 * SECS_PER_MIN)
|
||||
|
||||
|
@ -345,7 +345,6 @@ static int exfat_find_empty_entry(struct inode *inode,
|
||||
unsigned int ret, last_clu;
|
||||
loff_t size = 0;
|
||||
struct exfat_chain clu;
|
||||
struct exfat_dentry *ep = NULL;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
@ -410,25 +409,6 @@ static int exfat_find_empty_entry(struct inode *inode,
|
||||
p_dir->size++;
|
||||
size = EXFAT_CLU_TO_B(p_dir->size, sbi);
|
||||
|
||||
/* update the directory entry */
|
||||
if (p_dir->dir != sbi->root_dir) {
|
||||
struct buffer_head *bh;
|
||||
|
||||
ep = exfat_get_dentry(sb,
|
||||
&(ei->dir), ei->entry + 1, &bh);
|
||||
if (!ep)
|
||||
return -EIO;
|
||||
|
||||
ep->dentry.stream.valid_size = cpu_to_le64(size);
|
||||
ep->dentry.stream.size = ep->dentry.stream.valid_size;
|
||||
ep->dentry.stream.flags = p_dir->flags;
|
||||
exfat_update_bh(bh, IS_DIRSYNC(inode));
|
||||
brelse(bh);
|
||||
if (exfat_update_dir_chksum(inode, &(ei->dir),
|
||||
ei->entry))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* directory inode should be updated in here */
|
||||
i_size_write(inode, size);
|
||||
ei->i_size_ondisk += sbi->cluster_size;
|
||||
@ -489,7 +469,7 @@ static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
|
||||
return namelen; /* return error value */
|
||||
|
||||
if ((lossy && !lookup) || !namelen)
|
||||
return -EINVAL;
|
||||
return (lossy & NLS_NAME_OVERLEN) ? -ENAMETOOLONG : -EINVAL;
|
||||
|
||||
exfat_chain_set(p_dir, ei->start_clu,
|
||||
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
|
||||
|
@ -513,7 +513,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb,
|
||||
}
|
||||
|
||||
if (unilen > MAX_NAME_LENGTH) {
|
||||
exfat_err(sb, "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d",
|
||||
exfat_debug(sb, "failed to %s (estr:ENAMETOOLONG) nls len : %d, unilen : %d > %d",
|
||||
__func__, len, unilen, MAX_NAME_LENGTH);
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
@ -679,7 +679,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
|
||||
|
||||
bh = sb_bread(sb, sector);
|
||||
if (!bh) {
|
||||
exfat_err(sb, "failed to read sector(0x%llx)\n",
|
||||
exfat_err(sb, "failed to read sector(0x%llx)",
|
||||
(unsigned long long)sector);
|
||||
ret = -EIO;
|
||||
goto free_table;
|
||||
|
@ -547,9 +547,9 @@ static int parse_options(struct super_block *sb, char *options, int silent,
|
||||
break;
|
||||
default:
|
||||
if (!silent) {
|
||||
exfat_msg(sb, KERN_ERR,
|
||||
"unrecognized mount option \"%s\" or missing value",
|
||||
p);
|
||||
exfat_err(sb,
|
||||
"unrecognized mount option \"%s\" or missing value",
|
||||
p);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -559,14 +559,21 @@ out:
|
||||
if (opts->allow_utime == -1)
|
||||
opts->allow_utime = ~opts->fs_dmask & (0022);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
if (opts->discard && !bdev_max_discard_sectors(sb->s_bdev)) {
|
||||
exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard");
|
||||
opts->discard = 0;
|
||||
}
|
||||
#else
|
||||
if (opts->discard) {
|
||||
struct request_queue *q = bdev_get_queue(sb->s_bdev);
|
||||
|
||||
if (!blk_queue_discard(q))
|
||||
exfat_msg(sb, KERN_WARNING,
|
||||
"mounting with \"discard\" option, but the device does not support discard");
|
||||
opts->discard = 0;
|
||||
if (!blk_queue_discard(q)) {
|
||||
exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard");
|
||||
opts->discard = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -625,8 +632,8 @@ static int exfat_read_root(struct inode *inode)
|
||||
inode->i_op = &exfat_dir_inode_operations;
|
||||
inode->i_fop = &exfat_dir_operations;
|
||||
|
||||
inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) &
|
||||
~((loff_t)sbi->cluster_size - 1)) >> inode->i_blkbits;
|
||||
inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >>
|
||||
inode->i_blkbits;
|
||||
ei->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff;
|
||||
ei->i_size_aligned = i_size_read(inode);
|
||||
ei->i_size_ondisk = i_size_read(inode);
|
||||
@ -721,7 +728,7 @@ static int exfat_read_boot_sector(struct super_block *sb)
|
||||
*/
|
||||
if (p_boot->sect_size_bits < EXFAT_MIN_SECT_SIZE_BITS ||
|
||||
p_boot->sect_size_bits > EXFAT_MAX_SECT_SIZE_BITS) {
|
||||
exfat_err(sb, "bogus sector size bits : %u\n",
|
||||
exfat_err(sb, "bogus sector size bits : %u",
|
||||
p_boot->sect_size_bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -730,7 +737,7 @@ static int exfat_read_boot_sector(struct super_block *sb)
|
||||
* sect_per_clus_bits could be at least 0 and at most 25 - sect_size_bits.
|
||||
*/
|
||||
if (p_boot->sect_per_clus_bits > EXFAT_MAX_SECT_PER_CLUS_BITS(p_boot)) {
|
||||
exfat_err(sb, "bogus sectors bits per cluster : %u\n",
|
||||
exfat_err(sb, "bogus sectors bits per cluster : %u",
|
||||
p_boot->sect_per_clus_bits);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -896,6 +903,12 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
|
||||
if (opts->allow_utime == (unsigned short)-1)
|
||||
opts->allow_utime = ~opts->fs_dmask & 0022;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
|
||||
if (opts->discard && !bdev_max_discard_sectors(sb->s_bdev)) {
|
||||
exfat_warn(sb, "mounting with \"discard\" option, but the device does not support discard");
|
||||
opts->discard = 0;
|
||||
}
|
||||
#else
|
||||
if (opts->discard) {
|
||||
struct request_queue *q = bdev_get_queue(sb->s_bdev);
|
||||
|
||||
@ -904,6 +917,7 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
|
||||
opts->discard = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
struct exfat_sb_info *sbi;
|
||||
|
||||
@ -924,7 +938,7 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
|
||||
DEFAULT_RATELIMIT_BURST);
|
||||
err = parse_options(sb, data, silent, &sbi->options);
|
||||
if (err) {
|
||||
exfat_msg(sb, KERN_ERR, "failed to parse options");
|
||||
exfat_err(sb, "failed to parse options");
|
||||
goto check_nls_io;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user