Commit edb543cf authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 615bc218 5267456e
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -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++) {
		if (*uniname != 0x0) {
			ep->dentry.name.unicode_0_14[i] = cpu_to_le16(*uniname);
		if (*uniname == 0x0)
			break;
			uniname++;
		} else {
			ep->dentry.name.unicode_0_14[i] = 0x0;
		}
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -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;
+18 −1
Original line number Diff line number Diff line
@@ -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,
};
+11 −3
Original line number Diff line number Diff line
@@ -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,
			&sector_old);
		if (!epold)
			return -EIO;
		epnew = exfat_get_dentry(sb, p_dir, newentry + 1, &new_bh,
			&sector_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,
		&sector_mov);
	if (!epmov)
		return -EIO;
	epnew = exfat_get_dentry(sb, p_newdir, newentry + 1, &new_bh,
		&sector_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));
+10 −0
Original line number Diff line number Diff line
@@ -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)