Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9b9f8d5 authored by Eric Biggers's avatar Eric Biggers Committed by Theodore Ts'o
Browse files

ext4: clean up ext4_match() and callers



When ext4 encryption was originally merged, we were encrypting the
user-specified filename in ext4_match(), introducing a lot of additional
complexity into ext4_match() and its callers.  This has since been
changed to encrypt the filename earlier, so we can remove the gunk
that's no longer needed.  This more or less reverts ext4_search_dir()
and ext4_find_dest_de() to the way they were in the v4.0 kernel.

Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 1f73d491
Loading
Loading
Loading
Loading
+25 −56
Original line number Original line Diff line number Diff line
@@ -1237,18 +1237,17 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
}
}


/*
/*
 * NOTE! unlike strncmp, ext4_match returns 1 for success, 0 for failure.
 * Test whether a directory entry matches the filename being searched for.
 *
 *
 * `len <= EXT4_NAME_LEN' is guaranteed by caller.
 * Return: %true if the directory entry matches, otherwise %false.
 * `de != NULL' is guaranteed by caller.
 */
 */
static inline int ext4_match(struct ext4_filename *fname,
static inline bool ext4_match(const struct ext4_filename *fname,
			     struct ext4_dir_entry_2 *de)
			      const struct ext4_dir_entry_2 *de)
{
{
	struct fscrypt_name f;
	struct fscrypt_name f;


	if (!de->inode)
	if (!de->inode)
		return 0;
		return false;


	f.usr_fname = fname->usr_fname;
	f.usr_fname = fname->usr_fname;
	f.disk_name = fname->disk_name;
	f.disk_name = fname->disk_name;
@@ -1269,48 +1268,31 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
	struct ext4_dir_entry_2 * de;
	struct ext4_dir_entry_2 * de;
	char * dlimit;
	char * dlimit;
	int de_len;
	int de_len;
	int res;


	de = (struct ext4_dir_entry_2 *)search_buf;
	de = (struct ext4_dir_entry_2 *)search_buf;
	dlimit = search_buf + buf_size;
	dlimit = search_buf + buf_size;
	while ((char *) de < dlimit) {
	while ((char *) de < dlimit) {
		/* this code is executed quadratically often */
		/* this code is executed quadratically often */
		/* do minimal checking `by hand' */
		/* do minimal checking `by hand' */
		if ((char *) de + de->name_len <= dlimit) {
		if ((char *) de + de->name_len <= dlimit &&
			res = ext4_match(fname, de);
		    ext4_match(fname, de)) {
			if (res < 0) {
				res = -1;
				goto return_result;
			}
			if (res > 0) {
			/* found a match - just to be sure, do
			/* found a match - just to be sure, do
			 * a full check */
			 * a full check */
				if (ext4_check_dir_entry(dir, NULL, de, bh,
			if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
						bh->b_data,
						 bh->b_size, offset))
						 bh->b_size, offset)) {
				return -1;
					res = -1;
					goto return_result;
				}
			*res_dir = de;
			*res_dir = de;
				res = 1;
			return 1;
				goto return_result;
			}

		}
		}
		/* prevent looping on a bad block */
		/* prevent looping on a bad block */
		de_len = ext4_rec_len_from_disk(de->rec_len,
		de_len = ext4_rec_len_from_disk(de->rec_len,
						dir->i_sb->s_blocksize);
						dir->i_sb->s_blocksize);
		if (de_len <= 0) {
		if (de_len <= 0)
			res = -1;
			return -1;
			goto return_result;
		}
		offset += de_len;
		offset += de_len;
		de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
		de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
	}
	}

	return 0;
	res = 0;
return_result:
	return res;
}
}


static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
@@ -1814,24 +1796,15 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
	int nlen, rlen;
	int nlen, rlen;
	unsigned int offset = 0;
	unsigned int offset = 0;
	char *top;
	char *top;
	int res;


	de = (struct ext4_dir_entry_2 *)buf;
	de = (struct ext4_dir_entry_2 *)buf;
	top = buf + buf_size - reclen;
	top = buf + buf_size - reclen;
	while ((char *) de <= top) {
	while ((char *) de <= top) {
		if (ext4_check_dir_entry(dir, NULL, de, bh,
		if (ext4_check_dir_entry(dir, NULL, de, bh,
					 buf, buf_size, offset)) {
					 buf, buf_size, offset))
			res = -EFSCORRUPTED;
			return -EFSCORRUPTED;
			goto return_result;
		if (ext4_match(fname, de))
		}
			return -EEXIST;
		/* Provide crypto context and crypto buffer to ext4 match */
		res = ext4_match(fname, de);
		if (res < 0)
			goto return_result;
		if (res > 0) {
			res = -EEXIST;
			goto return_result;
		}
		nlen = EXT4_DIR_REC_LEN(de->name_len);
		nlen = EXT4_DIR_REC_LEN(de->name_len);
		rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
		rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
		if ((de->inode ? rlen - nlen : rlen) >= reclen)
		if ((de->inode ? rlen - nlen : rlen) >= reclen)
@@ -1839,15 +1812,11 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
		de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
		de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
		offset += rlen;
		offset += rlen;
	}
	}

	if ((char *) de > top)
	if ((char *) de > top)
		res = -ENOSPC;
		return -ENOSPC;
	else {

	*dest_de = de;
	*dest_de = de;
		res = 0;
	return 0;
	}
return_result:
	return res;
}
}


int ext4_insert_dentry(struct inode *dir,
int ext4_insert_dentry(struct inode *dir,