Commit 8170a99c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull exfat updates from Namjae Jeon:

 - If the start cluster of stream entry is invalid, treat it as the
   empty directory

 - Valid size of steam entry cannot be greater than data size. If
   valid_size is invalid, use data_size

 - Move Direct-IO alignment check to before extending the valid size

 - Fix uninit-value issue reported by syzbot

 - Optimize finding directory entry-set in write_inode, rename, unlink

* tag 'exfat-for-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat:
  exfat: reduce FAT chain traversal
  exfat: code cleanup for exfat_readdir()
  exfat: remove argument 'p_dir' from exfat_add_entry()
  exfat: move exfat_chain_set() out of __exfat_resolve_path()
  exfat: add exfat_get_dentry_set_by_ei() helper
  exfat: rename argument name for exfat_move_file and exfat_rename_file
  exfat: remove unnecessary read entry in __exfat_rename()
  exfat: fix file being changed by unaligned direct write
  exfat: fix uninit-value in __exfat_get_dentry_set
  exfat: fix out-of-bounds access of directory entries
parents b86545e0 8a3f5711
Loading
Loading
Loading
Loading
+5 −24
Original line number Diff line number Diff line
@@ -82,9 +82,6 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
	if (ei->type != TYPE_DIR)
		return -EPERM;

	if (ei->entry == -1)
		exfat_chain_set(&dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
	else
	exfat_chain_set(&dir, ei->start_clu,
		EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);

@@ -135,21 +132,6 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent

			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,
					ep->dentry.file.create_time,
					ep->dentry.file.create_date,
					ep->dentry.file.create_time_cs);
			exfat_get_entry_time(sbi, &dir_entry->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, &dir_entry->atime,
					ep->dentry.file.access_tz,
					ep->dentry.file.access_time,
					ep->dentry.file.access_date,
					0);

			*uni_name.name = 0x0;
			err = exfat_get_uniname_from_ext_entry(sb, &clu, i,
@@ -166,9 +148,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
			ep = exfat_get_dentry(sb, &clu, i + 1, &bh);
			if (!ep)
				return -EIO;
			dir_entry->size =
				le64_to_cpu(ep->dentry.stream.valid_size);
			dir_entry->entry = dentry;
			dir_entry->entry = i;
			dir_entry->dir = clu;
			brelse(bh);

			ei->hint_bmap.off = EXFAT_DEN_TO_CLU(dentry, sbi);
@@ -276,7 +257,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
	if (!nb->lfn[0])
		goto end_of_dir;

	i_pos = ((loff_t)ei->start_clu << 32) |	(de.entry & 0xffffffff);
	i_pos = ((loff_t)de.dir.dir << 32) | (de.entry & 0xffffffff);
	tmp = exfat_iget(sb, i_pos);
	if (tmp) {
		inum = tmp->i_ino;
+6 −0
Original line number Diff line number Diff line
@@ -204,7 +204,9 @@ struct exfat_entry_set_cache {
#define IS_DYNAMIC_ES(es)	((es)->__bh != (es)->bh)

struct exfat_dir_entry {
	/* the cluster where file dentry is located */
	struct exfat_chain dir;
	/* the index of file dentry in ->dir */
	int entry;
	unsigned int type;
	unsigned int start_clu;
@@ -290,7 +292,9 @@ struct exfat_sb_info {
 * EXFAT file system inode in-memory data
 */
struct exfat_inode_info {
	/* the cluster where file dentry is located */
	struct exfat_chain dir;
	/* the index of file dentry in ->dir */
	int entry;
	unsigned int type;
	unsigned short attr;
@@ -508,6 +512,8 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
		struct super_block *sb, struct exfat_chain *p_dir, int entry,
		unsigned int num_entries);
#define exfat_get_dentry_set_by_ei(es, sb, ei)		\
	exfat_get_dentry_set(es, sb, &(ei)->dir, (ei)->entry, ES_ALL_ENTRIES)
int exfat_get_empty_dentry_set(struct exfat_entry_set_cache *es,
		struct super_block *sb, struct exfat_chain *p_dir, int entry,
		unsigned int num_entries);
+10 −0
Original line number Diff line number Diff line
@@ -584,6 +584,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
	if (ret < 0)
		goto unlock;

	if (iocb->ki_flags & IOCB_DIRECT) {
		unsigned long align = pos | iov_iter_alignment(iter);

		if (!IS_ALIGNED(align, i_blocksize(inode)) &&
		    !IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) {
			ret = -EINVAL;
			goto unlock;
		}
	}

	if (pos > valid_size) {
		ret = exfat_extend_valid_size(file, pos);
		if (ret < 0 && ret != -ENOSPC) {
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ int __exfat_write_inode(struct inode *inode, int sync)
	exfat_set_volume_dirty(sb);

	/* get the directory entry of given file or directory */
	if (exfat_get_dentry_set(&es, sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES))
	if (exfat_get_dentry_set_by_ei(&es, sb, ei))
		return -EIO;
	ep = exfat_get_dentry_cached(&es, ES_IDX_FILE);
	ep2 = exfat_get_dentry_cached(&es, ES_IDX_STREAM);
+91 −103
Original line number Diff line number Diff line
@@ -288,8 +288,22 @@ static int exfat_check_max_dentries(struct inode *inode)
	return 0;
}

/* find empty directory entry.
 * if there isn't any empty slot, expand cluster chain.
/*
 * Find an empty directory entry set.
 *
 * If there isn't any empty slot, expand cluster chain.
 *
 * in:
 *   inode: inode of the parent directory
 *   num_entries: specifies how many dentries in the empty directory entry set
 *
 * out:
 *   p_dir: the cluster where the empty directory entry set is located
 *   es: The found empty directory entry set
 *
 * return:
 *   the directory entry index in p_dir is returned on succeeds
 *   -error code is returned on failure
 */
static int exfat_find_empty_entry(struct inode *inode,
		struct exfat_chain *p_dir, int num_entries,
@@ -311,6 +325,9 @@ static int exfat_find_empty_entry(struct inode *inode,
		ei->hint_femp.eidx = EXFAT_HINT_NONE;
	}

	exfat_chain_set(p_dir, ei->start_clu,
			EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);

	while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir,
					num_entries, es)) < 0) {
		if (dentry == -EIO)
@@ -345,6 +362,7 @@ static int exfat_find_empty_entry(struct inode *inode,
		if (ei->start_clu == EXFAT_EOF_CLUSTER) {
			ei->start_clu = clu.dir;
			p_dir->dir = clu.dir;
			hint_femp.eidx = 0;
		}

		/* append to the FAT chain */
@@ -377,7 +395,10 @@ static int exfat_find_empty_entry(struct inode *inode,
		inode->i_blocks += sbi->cluster_size >> 9;
	}

	return dentry;
	p_dir->dir = exfat_sector_to_cluster(sbi, es->bh[0]->b_blocknr);
	p_dir->size -= dentry / sbi->dentries_per_clu;

	return dentry & (sbi->dentries_per_clu - 1);
}

/*
@@ -385,14 +406,11 @@ static int exfat_find_empty_entry(struct inode *inode,
 * Zero if it was successful; otherwise nonzero.
 */
static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
		struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
		int lookup)
		struct exfat_uni_name *p_uniname, int lookup)
{
	int namelen;
	int lossy = NLS_NAME_NO_LOSSY;
	struct super_block *sb = inode->i_sb;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	struct exfat_inode_info *ei = EXFAT_I(inode);
	int pathlen = strlen(path);

	/*
@@ -431,24 +449,19 @@ static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
	if ((lossy && !lookup) || !namelen)
		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);

	return 0;
}

static inline int exfat_resolve_path(struct inode *inode,
		const unsigned char *path, struct exfat_chain *dir,
		struct exfat_uni_name *uni)
		const unsigned char *path, struct exfat_uni_name *uni)
{
	return __exfat_resolve_path(inode, path, dir, uni, 0);
	return __exfat_resolve_path(inode, path, uni, 0);
}

static inline int exfat_resolve_path_for_lookup(struct inode *inode,
		const unsigned char *path, struct exfat_chain *dir,
		struct exfat_uni_name *uni)
		const unsigned char *path, struct exfat_uni_name *uni)
{
	return __exfat_resolve_path(inode, path, dir, uni, 1);
	return __exfat_resolve_path(inode, path, uni, 1);
}

static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info)
@@ -457,8 +470,7 @@ static inline loff_t exfat_make_i_pos(struct exfat_dir_entry *info)
}

static int exfat_add_entry(struct inode *inode, const char *path,
		struct exfat_chain *p_dir, unsigned int type,
		struct exfat_dir_entry *info)
		unsigned int type, struct exfat_dir_entry *info)
{
	int ret, dentry, num_entries;
	struct super_block *sb = inode->i_sb;
@@ -470,7 +482,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
	int clu_size = 0;
	unsigned int start_clu = EXFAT_FREE_CLUSTER;

	ret = exfat_resolve_path(inode, path, p_dir, &uniname);
	ret = exfat_resolve_path(inode, path, &uniname);
	if (ret)
		goto out;

@@ -481,7 +493,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
	}

	/* exfat_find_empty_entry must be called before alloc_cluster() */
	dentry = exfat_find_empty_entry(inode, p_dir, num_entries, &es);
	dentry = exfat_find_empty_entry(inode, &info->dir, num_entries, &es);
	if (dentry < 0) {
		ret = dentry; /* -EIO or -ENOSPC */
		goto out;
@@ -508,7 +520,6 @@ static int exfat_add_entry(struct inode *inode, const char *path,
	if (ret)
		goto out;

	info->dir = *p_dir;
	info->entry = dentry;
	info->flags = ALLOC_NO_FAT_CHAIN;
	info->type = type;
@@ -541,7 +552,6 @@ static int exfat_create(struct mnt_idmap *idmap, struct inode *dir,
{
	struct super_block *sb = dir->i_sb;
	struct inode *inode;
	struct exfat_chain cdir;
	struct exfat_dir_entry info;
	loff_t i_pos;
	int err;
@@ -552,8 +562,7 @@ static int exfat_create(struct mnt_idmap *idmap, struct inode *dir,

	mutex_lock(&EXFAT_SB(sb)->s_lock);
	exfat_set_volume_dirty(sb);
	err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
		&info);
	err = exfat_add_entry(dir, dentry->d_name.name, TYPE_FILE, &info);
	if (err)
		goto unlock;

@@ -601,10 +610,13 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
		return -ENOENT;

	/* check the validity of directory name in the given pathname */
	ret = exfat_resolve_path_for_lookup(dir, qname->name, &cdir, &uni_name);
	ret = exfat_resolve_path_for_lookup(dir, qname->name, &uni_name);
	if (ret)
		return ret;

	exfat_chain_set(&cdir, ei->start_clu,
		EXFAT_B_TO_CLU(i_size_read(dir), sbi), ei->flags);

	/* check the validation of hint_stat and initialize it if required */
	if (ei->version != (inode_peek_iversion_raw(dir) & 0xffffffff)) {
		ei->hint_stat.clu = cdir.dir;
@@ -618,15 +630,16 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
	if (dentry < 0)
		return dentry; /* -error value */

	info->dir = cdir;
	info->entry = dentry;
	info->num_subdirs = 0;

	/* adjust cdir to the optimized value */
	cdir.dir = hint_opt.clu;
	if (cdir.flags & ALLOC_NO_FAT_CHAIN)
		cdir.size -= dentry / sbi->dentries_per_clu;
	dentry = hint_opt.eidx;

	info->dir = cdir;
	info->entry = dentry;
	info->num_subdirs = 0;

	if (exfat_get_dentry_set(&es, sb, &cdir, dentry, ES_2_ENTRIES))
		return -EIO;
	ep = exfat_get_dentry_cached(&es, ES_IDX_FILE);
@@ -637,14 +650,26 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
	info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
	info->valid_size = le64_to_cpu(ep2->dentry.stream.valid_size);
	info->size = le64_to_cpu(ep2->dentry.stream.size);

	info->start_clu = le32_to_cpu(ep2->dentry.stream.start_clu);
	if (!is_valid_cluster(sbi, info->start_clu) && info->size) {
		exfat_warn(sb, "start_clu is invalid cluster(0x%x)",
				info->start_clu);
		info->size = 0;
		info->valid_size = 0;
	}

	if (info->valid_size > info->size) {
		exfat_warn(sb, "valid_size(%lld) is greater than size(%lld)",
				info->valid_size, info->size);
		info->valid_size = info->size;
	}

	if (info->size == 0) {
		info->flags = ALLOC_NO_FAT_CHAIN;
		info->start_clu = EXFAT_EOF_CLUSTER;
	} else {
	} else
		info->flags = ep2->dentry.stream.flags;
		info->start_clu =
			le32_to_cpu(ep2->dentry.stream.start_clu);
	}

	exfat_get_entry_time(sbi, &info->crtime,
			     ep->dentry.file.create_tz,
@@ -766,26 +791,23 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
/* remove an entry, BUT don't truncate */
static int exfat_unlink(struct inode *dir, struct dentry *dentry)
{
	struct exfat_chain cdir;
	struct super_block *sb = dir->i_sb;
	struct inode *inode = dentry->d_inode;
	struct exfat_inode_info *ei = EXFAT_I(inode);
	struct exfat_entry_set_cache es;
	int entry, err = 0;
	int err = 0;

	if (unlikely(exfat_forced_shutdown(sb)))
		return -EIO;

	mutex_lock(&EXFAT_SB(sb)->s_lock);
	exfat_chain_dup(&cdir, &ei->dir);
	entry = ei->entry;
	if (ei->dir.dir == DIR_DELETED) {
		exfat_err(sb, "abnormal access to deleted dentry");
		err = -ENOENT;
		goto unlock;
	}

	err = exfat_get_dentry_set(&es, sb, &cdir, entry, ES_ALL_ENTRIES);
	err = exfat_get_dentry_set_by_ei(&es, sb, ei);
	if (err) {
		err = -EIO;
		goto unlock;
@@ -824,7 +846,6 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
	struct super_block *sb = dir->i_sb;
	struct inode *inode;
	struct exfat_dir_entry info;
	struct exfat_chain cdir;
	loff_t i_pos;
	int err;
	loff_t size = i_size_read(dir);
@@ -834,8 +855,7 @@ static int exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,

	mutex_lock(&EXFAT_SB(sb)->s_lock);
	exfat_set_volume_dirty(sb);
	err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
		&info);
	err = exfat_add_entry(dir, dentry->d_name.name, TYPE_DIR, &info);
	if (err)
		goto unlock;

@@ -915,21 +935,18 @@ static int exfat_check_dir_empty(struct super_block *sb,
static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	struct exfat_chain cdir, clu_to_free;
	struct exfat_chain clu_to_free;
	struct super_block *sb = inode->i_sb;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	struct exfat_inode_info *ei = EXFAT_I(inode);
	struct exfat_entry_set_cache es;
	int entry, err;
	int err;

	if (unlikely(exfat_forced_shutdown(sb)))
		return -EIO;

	mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);

	exfat_chain_dup(&cdir, &ei->dir);
	entry = ei->entry;

	if (ei->dir.dir == DIR_DELETED) {
		exfat_err(sb, "abnormal access to deleted dentry");
		err = -ENOENT;
@@ -947,7 +964,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
		goto unlock;
	}

	err = exfat_get_dentry_set(&es, sb, &cdir, entry, ES_ALL_ENTRIES);
	err = exfat_get_dentry_set_by_ei(&es, sb, ei);
	if (err) {
		err = -EIO;
		goto unlock;
@@ -982,15 +999,14 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
	return err;
}

static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
		int oldentry, struct exfat_uni_name *p_uniname,
		struct exfat_inode_info *ei)
static int exfat_rename_file(struct inode *parent_inode,
		struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei)
{
	int ret, num_new_entries;
	struct exfat_dentry *epold, *epnew;
	struct super_block *sb = inode->i_sb;
	struct super_block *sb = parent_inode->i_sb;
	struct exfat_entry_set_cache old_es, new_es;
	int sync = IS_DIRSYNC(inode);
	int sync = IS_DIRSYNC(parent_inode);

	if (unlikely(exfat_forced_shutdown(sb)))
		return -EIO;
@@ -999,7 +1015,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
	if (num_new_entries < 0)
		return num_new_entries;

	ret = exfat_get_dentry_set(&old_es, sb, p_dir, oldentry, ES_ALL_ENTRIES);
	ret = exfat_get_dentry_set_by_ei(&old_es, sb, ei);
	if (ret) {
		ret = -EIO;
		return ret;
@@ -1009,9 +1025,10 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,

	if (old_es.num_entries < num_new_entries) {
		int newentry;
		struct exfat_chain dir;

		newentry = exfat_find_empty_entry(inode, p_dir, num_new_entries,
				&new_es);
		newentry = exfat_find_empty_entry(parent_inode, &dir,
				num_new_entries, &new_es);
		if (newentry < 0) {
			ret = newentry; /* -EIO or -ENOSPC */
			goto put_old_es;
@@ -1034,8 +1051,8 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
		if (ret)
			goto put_old_es;

		exfat_remove_entries(inode, &old_es, ES_IDX_FILE);
		ei->dir = *p_dir;
		exfat_remove_entries(parent_inode, &old_es, ES_IDX_FILE);
		ei->dir = dir;
		ei->entry = newentry;
	} else {
		if (exfat_get_entry_type(epold) == TYPE_FILE) {
@@ -1043,7 +1060,7 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
			ei->attr |= EXFAT_ATTR_ARCHIVE;
		}

		exfat_remove_entries(inode, &old_es, ES_IDX_FIRST_FILENAME + 1);
		exfat_remove_entries(parent_inode, &old_es, ES_IDX_FIRST_FILENAME + 1);
		exfat_init_ext_entry(&old_es, num_new_entries, p_uniname);
	}
	return exfat_put_dentry_set(&old_es, sync);
@@ -1053,26 +1070,24 @@ static int exfat_rename_file(struct inode *inode, struct exfat_chain *p_dir,
	return ret;
}

static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
		int oldentry, struct exfat_chain *p_newdir,
static int exfat_move_file(struct inode *parent_inode,
		struct exfat_uni_name *p_uniname, struct exfat_inode_info *ei)
{
	int ret, newentry, num_new_entries;
	struct exfat_dentry *epmov, *epnew;
	struct super_block *sb = inode->i_sb;
	struct exfat_entry_set_cache mov_es, new_es;
	struct exfat_chain newdir;

	num_new_entries = exfat_calc_num_entries(p_uniname);
	if (num_new_entries < 0)
		return num_new_entries;

	ret = exfat_get_dentry_set(&mov_es, sb, p_olddir, oldentry,
			ES_ALL_ENTRIES);
	ret = exfat_get_dentry_set_by_ei(&mov_es, parent_inode->i_sb, ei);
	if (ret)
		return -EIO;

	newentry = exfat_find_empty_entry(inode, p_newdir, num_new_entries,
			&new_es);
	newentry = exfat_find_empty_entry(parent_inode, &newdir,
			num_new_entries, &new_es);
	if (newentry < 0) {
		ret = newentry; /* -EIO or -ENOSPC */
		goto put_mov_es;
@@ -1091,18 +1106,16 @@ static int exfat_move_file(struct inode *inode, struct exfat_chain *p_olddir,
	*epnew = *epmov;

	exfat_init_ext_entry(&new_es, num_new_entries, p_uniname);
	exfat_remove_entries(inode, &mov_es, ES_IDX_FILE);

	exfat_chain_set(&ei->dir, p_newdir->dir, p_newdir->size,
		p_newdir->flags);
	exfat_remove_entries(parent_inode, &mov_es, ES_IDX_FILE);

	ei->dir = newdir;
	ei->entry = newentry;

	ret = exfat_put_dentry_set(&new_es, IS_DIRSYNC(inode));
	ret = exfat_put_dentry_set(&new_es, IS_DIRSYNC(parent_inode));
	if (ret)
		goto put_mov_es;

	return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(inode));
	return exfat_put_dentry_set(&mov_es, IS_DIRSYNC(parent_inode));

put_mov_es:
	exfat_put_dentry_set(&mov_es, false);
@@ -1116,19 +1129,12 @@ static int __exfat_rename(struct inode *old_parent_inode,
		struct dentry *new_dentry)
{
	int ret;
	int dentry;
	struct exfat_chain olddir, newdir;
	struct exfat_chain *p_dir = NULL;
	struct exfat_uni_name uni_name;
	struct exfat_dentry *ep;
	struct super_block *sb = old_parent_inode->i_sb;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	const unsigned char *new_path = new_dentry->d_name.name;
	struct inode *new_inode = new_dentry->d_inode;
	struct exfat_inode_info *new_ei = NULL;
	unsigned int new_entry_type = TYPE_UNUSED;
	int new_entry = 0;
	struct buffer_head *new_bh = NULL;

	/* check the validity of pointer parameters */
	if (new_path == NULL || strlen(new_path) == 0)
@@ -1139,11 +1145,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
		return -ENOENT;
	}

	exfat_chain_set(&olddir, EXFAT_I(old_parent_inode)->start_clu,
		EXFAT_B_TO_CLU_ROUND_UP(i_size_read(old_parent_inode), sbi),
		EXFAT_I(old_parent_inode)->flags);
	dentry = ei->entry;

	/* check whether new dir is existing directory and empty */
	if (new_inode) {
		ret = -EIO;
@@ -1154,17 +1155,8 @@ static int __exfat_rename(struct inode *old_parent_inode,
			goto out;
		}

		p_dir = &(new_ei->dir);
		new_entry = new_ei->entry;
		ep = exfat_get_dentry(sb, p_dir, new_entry, &new_bh);
		if (!ep)
			goto out;

		new_entry_type = exfat_get_entry_type(ep);
		brelse(new_bh);

		/* if new_inode exists, update ei */
		if (new_entry_type == TYPE_DIR) {
		if (S_ISDIR(new_inode->i_mode)) {
			struct exfat_chain new_clu;

			new_clu.dir = new_ei->start_clu;
@@ -1180,26 +1172,22 @@ static int __exfat_rename(struct inode *old_parent_inode,
	}

	/* check the validity of directory name in the given new pathname */
	ret = exfat_resolve_path(new_parent_inode, new_path, &newdir,
			&uni_name);
	ret = exfat_resolve_path(new_parent_inode, new_path, &uni_name);
	if (ret)
		goto out;

	exfat_set_volume_dirty(sb);

	if (olddir.dir == newdir.dir)
		ret = exfat_rename_file(new_parent_inode, &olddir, dentry,
				&uni_name, ei);
	if (new_parent_inode == old_parent_inode)
		ret = exfat_rename_file(new_parent_inode, &uni_name, ei);
	else
		ret = exfat_move_file(new_parent_inode, &olddir, dentry,
				&newdir, &uni_name, ei);
		ret = exfat_move_file(new_parent_inode, &uni_name, ei);

	if (!ret && new_inode) {
		struct exfat_entry_set_cache es;

		/* delete entries of new_dir */
		ret = exfat_get_dentry_set(&es, sb, p_dir, new_entry,
				ES_ALL_ENTRIES);
		ret = exfat_get_dentry_set_by_ei(&es, sb, new_ei);
		if (ret) {
			ret = -EIO;
			goto del_out;
@@ -1212,7 +1200,7 @@ static int __exfat_rename(struct inode *old_parent_inode,
			goto del_out;

		/* Free the clusters if new_inode is a dir(as if exfat_rmdir) */
		if (new_entry_type == TYPE_DIR &&
		if (S_ISDIR(new_inode->i_mode) &&
		    new_ei->start_clu != EXFAT_EOF_CLUSTER) {
			/* new_ei, new_clu_to_free */
			struct exfat_chain new_clu_to_free;