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

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
...@@ -1237,18 +1237,17 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment