Merge tag 'exfat-for-5.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat fixes from Namjae Jeon: - Zero out unused characters of FileName field to avoid a complaint from some fsck tool. - Fix memory leak on error paths. - Fix unnecessary VOL_DIRTY set when calling rmdir on non-empty directory. - Call sync_filesystem() for read-only remount (Fix generic/452 test in xfstests) - Add own fsync() to flush dirty metadata. * tag 'exfat-for-5.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: flush dirty metadata in fsync exfat: move setting VOL_DIRTY over exfat_remove_entries() exfat: call sync_filesystem for read-only remount exfat: add missing brelse() calls on error paths exfat: Set the unused characters of FileName field to the value 0000h
This commit is contained in:
@@ -309,7 +309,7 @@ const struct file_operations exfat_dir_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.iterate = exfat_iterate,
|
||||
.fsync = generic_file_fsync,
|
||||
.fsync = exfat_file_fsync,
|
||||
};
|
||||
|
||||
int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu)
|
||||
@@ -425,10 +425,12 @@ static void exfat_init_name_entry(struct exfat_dentry *ep,
|
||||
ep->dentry.name.flags = 0x0;
|
||||
|
||||
for (i = 0; i < EXFAT_FILE_NAME_LEN; i++) {
|
||||
ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname);
|
||||
if (*uniname == 0x0)
|
||||
break;
|
||||
uniname++;
|
||||
if (*uniname != 0x0) {
|
||||
ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname);
|
||||
uniname++;
|
||||
} else {
|
||||
ep->dentry.name.unicode_0_14[i] = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -420,6 +420,7 @@ void exfat_truncate(struct inode *inode, loff_t size);
|
||||
int exfat_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int exfat_getattr(const struct path *path, struct kstat *stat,
|
||||
unsigned int request_mask, unsigned int query_flags);
|
||||
int exfat_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
|
||||
|
||||
/* namei.c */
|
||||
extern const struct dentry_operations exfat_dentry_ops;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include "exfat_raw.h"
|
||||
#include "exfat_fs.h"
|
||||
@@ -346,12 +347,28 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
|
||||
{
|
||||
struct inode *inode = filp->f_mapping->host;
|
||||
int err;
|
||||
|
||||
err = __generic_file_fsync(filp, start, end, datasync);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = sync_blockdev(inode->i_sb->s_bdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL);
|
||||
}
|
||||
|
||||
const struct file_operations exfat_file_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.mmap = generic_file_mmap,
|
||||
.fsync = generic_file_fsync,
|
||||
.fsync = exfat_file_fsync,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
};
|
||||
|
||||
@@ -975,7 +975,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
exfat_chain_set(&clu_to_free, ei->start_clu,
|
||||
EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi), ei->flags);
|
||||
|
||||
@@ -1002,6 +1001,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
num_entries++;
|
||||
brelse(bh);
|
||||
|
||||
exfat_set_vol_flags(sb, VOL_DIRTY);
|
||||
err = exfat_remove_entries(dir, &cdir, entry, 0, num_entries);
|
||||
if (err) {
|
||||
exfat_err(sb, "failed to exfat_remove_entries : err(%d)", err);
|
||||
@@ -1077,10 +1077,14 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
|
||||
|
||||
epold = exfat_get_dentry(sb, p_dir, oldentry + 1, &old_bh,
|
||||
§or_old);
|
||||
if (!epold)
|
||||
return -EIO;
|
||||
epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh,
|
||||
§or_new);
|
||||
if (!epold || !epnew)
|
||||
if (!epnew) {
|
||||
brelse(old_bh);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(epnew, epold, DENTRY_SIZE);
|
||||
exfat_update_bh(sb, new_bh, sync);
|
||||
@@ -1161,10 +1165,14 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
|
||||
|
||||
epmov = exfat_get_dentry(sb, p_olddir, oldentry + 1, &mov_bh,
|
||||
§or_mov);
|
||||
if (!epmov)
|
||||
return -EIO;
|
||||
epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh,
|
||||
§or_new);
|
||||
if (!epmov || !epnew)
|
||||
if (!epnew) {
|
||||
brelse(mov_bh);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(epnew, epmov, DENTRY_SIZE);
|
||||
exfat_update_bh(sb, new_bh, IS_DIRSYNC(inode));
|
||||
|
||||
@@ -693,10 +693,20 @@ static void exfat_free(struct fs_context *fc)
|
||||
}
|
||||
}
|
||||
|
||||
static int exfat_reconfigure(struct fs_context *fc)
|
||||
{
|
||||
fc->sb_flags |= SB_NODIRATIME;
|
||||
|
||||
/* volume flag will be updated in exfat_sync_fs */
|
||||
sync_filesystem(fc->root->d_sb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fs_context_operations exfat_context_ops = {
|
||||
.parse_param = exfat_parse_param,
|
||||
.get_tree = exfat_get_tree,
|
||||
.free = exfat_free,
|
||||
.reconfigure = exfat_reconfigure,
|
||||
};
|
||||
|
||||
static int exfat_init_fs_context(struct fs_context *fc)
|
||||
|
||||
Reference in New Issue
Block a user