mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Revert "ANDROID: ext4: Handle casefolding with encryption"
This reverts commit b10c4acd41e8b15cff1119e2100adf36b013b840. Signed-off-by: Daniel Rosenberg <drosen@google.com> Change-Id: I6e036e92492d34e2a7bafeab98eae780a7aa2355
This commit is contained in:
parent
0bedb20065
commit
bfec958d8b
@ -29,8 +29,6 @@
|
|||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
#include "xattr.h"
|
#include "xattr.h"
|
||||||
|
|
||||||
#define DOTDOT_OFFSET 12
|
|
||||||
|
|
||||||
static int ext4_dx_readdir(struct file *, struct dir_context *);
|
static int ext4_dx_readdir(struct file *, struct dir_context *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,19 +51,6 @@ static int is_dx_dir(struct inode *inode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_fake_entry(struct inode *dir, ext4_lblk_t lblk,
|
|
||||||
unsigned int offset, unsigned int blocksize)
|
|
||||||
{
|
|
||||||
/* Entries in the first block before this value refer to . or .. */
|
|
||||||
if (lblk == 0 && offset <= DOTDOT_OFFSET)
|
|
||||||
return true;
|
|
||||||
/* Check if this is likely the csum entry */
|
|
||||||
if (ext4_has_metadata_csum(dir->i_sb) && offset % blocksize ==
|
|
||||||
blocksize - sizeof(struct ext4_dir_entry_tail))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return 0 if the directory entry is OK, and 1 if there is a problem
|
* Return 0 if the directory entry is OK, and 1 if there is a problem
|
||||||
*
|
*
|
||||||
@ -78,30 +63,25 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
|
|||||||
struct inode *dir, struct file *filp,
|
struct inode *dir, struct file *filp,
|
||||||
struct ext4_dir_entry_2 *de,
|
struct ext4_dir_entry_2 *de,
|
||||||
struct buffer_head *bh, char *buf, int size,
|
struct buffer_head *bh, char *buf, int size,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
unsigned int offset)
|
unsigned int offset)
|
||||||
{
|
{
|
||||||
const char *error_msg = NULL;
|
const char *error_msg = NULL;
|
||||||
const int rlen = ext4_rec_len_from_disk(de->rec_len,
|
const int rlen = ext4_rec_len_from_disk(de->rec_len,
|
||||||
dir->i_sb->s_blocksize);
|
dir->i_sb->s_blocksize);
|
||||||
const int next_offset = ((char *) de - buf) + rlen;
|
|
||||||
unsigned int blocksize = dir->i_sb->s_blocksize;
|
|
||||||
bool fake = is_fake_entry(dir, lblk, offset, blocksize);
|
|
||||||
bool next_fake = is_fake_entry(dir, lblk, next_offset, blocksize);
|
|
||||||
|
|
||||||
if (unlikely(rlen < ext4_dir_rec_len(1, fake ? NULL : dir)))
|
if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
|
||||||
error_msg = "rec_len is smaller than minimal";
|
error_msg = "rec_len is smaller than minimal";
|
||||||
else if (unlikely(rlen % 4 != 0))
|
else if (unlikely(rlen % 4 != 0))
|
||||||
error_msg = "rec_len % 4 != 0";
|
error_msg = "rec_len % 4 != 0";
|
||||||
else if (unlikely(rlen < ext4_dir_rec_len(de->name_len,
|
else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
|
||||||
fake ? NULL : dir)))
|
|
||||||
error_msg = "rec_len is too small for name_len";
|
error_msg = "rec_len is too small for name_len";
|
||||||
else if (unlikely(((char *) de - buf) + rlen > size))
|
else if (unlikely(((char *) de - buf) + rlen > size))
|
||||||
error_msg = "directory entry overrun";
|
error_msg = "directory entry overrun";
|
||||||
else if (unlikely(next_offset > size - ext4_dir_rec_len(1,
|
else if (unlikely(((char *) de - buf) + rlen >
|
||||||
next_fake ? NULL : dir) &&
|
size - EXT4_DIR_REC_LEN(1) &&
|
||||||
next_offset != size))
|
((char *) de - buf) + rlen != size)) {
|
||||||
error_msg = "directory entry too close to block end";
|
error_msg = "directory entry too close to block end";
|
||||||
|
}
|
||||||
else if (unlikely(le32_to_cpu(de->inode) >
|
else if (unlikely(le32_to_cpu(de->inode) >
|
||||||
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
|
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
|
||||||
error_msg = "inode out of bounds";
|
error_msg = "inode out of bounds";
|
||||||
@ -111,15 +91,15 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
|
|||||||
if (filp)
|
if (filp)
|
||||||
ext4_error_file(filp, function, line, bh->b_blocknr,
|
ext4_error_file(filp, function, line, bh->b_blocknr,
|
||||||
"bad entry in directory: %s - offset=%u, "
|
"bad entry in directory: %s - offset=%u, "
|
||||||
"inode=%u, rec_len=%d, lblk=%d, size=%d fake=%d",
|
"inode=%u, rec_len=%d, name_len=%d, size=%d",
|
||||||
error_msg, offset, le32_to_cpu(de->inode),
|
error_msg, offset, le32_to_cpu(de->inode),
|
||||||
rlen, lblk, size, fake);
|
rlen, de->name_len, size);
|
||||||
else
|
else
|
||||||
ext4_error_inode(dir, function, line, bh->b_blocknr,
|
ext4_error_inode(dir, function, line, bh->b_blocknr,
|
||||||
"bad entry in directory: %s - offset=%u, "
|
"bad entry in directory: %s - offset=%u, "
|
||||||
"inode=%u, rec_len=%d, lblk=%d, size=%d fake=%d",
|
"inode=%u, rec_len=%d, name_len=%d, size=%d",
|
||||||
error_msg, offset, le32_to_cpu(de->inode),
|
error_msg, offset, le32_to_cpu(de->inode),
|
||||||
rlen, lblk, size, fake);
|
rlen, de->name_len, size);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -244,8 +224,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
|||||||
* failure will be detected in the
|
* failure will be detected in the
|
||||||
* dirent test below. */
|
* dirent test below. */
|
||||||
if (ext4_rec_len_from_disk(de->rec_len,
|
if (ext4_rec_len_from_disk(de->rec_len,
|
||||||
sb->s_blocksize) < ext4_dir_rec_len(1,
|
sb->s_blocksize) < EXT4_DIR_REC_LEN(1))
|
||||||
inode))
|
|
||||||
break;
|
break;
|
||||||
i += ext4_rec_len_from_disk(de->rec_len,
|
i += ext4_rec_len_from_disk(de->rec_len,
|
||||||
sb->s_blocksize);
|
sb->s_blocksize);
|
||||||
@ -261,7 +240,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
|||||||
de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
|
de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
|
||||||
if (ext4_check_dir_entry(inode, file, de, bh,
|
if (ext4_check_dir_entry(inode, file, de, bh,
|
||||||
bh->b_data, bh->b_size,
|
bh->b_data, bh->b_size,
|
||||||
map.m_lblk, offset)) {
|
offset)) {
|
||||||
/*
|
/*
|
||||||
* On error, skip to the next block
|
* On error, skip to the next block
|
||||||
*/
|
*/
|
||||||
@ -286,9 +265,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
|||||||
|
|
||||||
/* Directory is encrypted */
|
/* Directory is encrypted */
|
||||||
err = fscrypt_fname_disk_to_usr(inode,
|
err = fscrypt_fname_disk_to_usr(inode,
|
||||||
EXT4_DIRENT_HASH(de),
|
0, 0, &de_name, &fstr);
|
||||||
EXT4_DIRENT_MINOR_HASH(de),
|
|
||||||
&de_name, &fstr);
|
|
||||||
de_name = fstr;
|
de_name = fstr;
|
||||||
fstr.len = save_len;
|
fstr.len = save_len;
|
||||||
if (err)
|
if (err)
|
||||||
@ -663,7 +640,7 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
|
|||||||
top = buf + buf_size;
|
top = buf + buf_size;
|
||||||
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, 0, offset))
|
buf, buf_size, offset))
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
|
rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
|
||||||
de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
|
de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
|
||||||
|
@ -1967,17 +1967,6 @@ struct ext4_dir_entry {
|
|||||||
char name[EXT4_NAME_LEN]; /* File name */
|
char name[EXT4_NAME_LEN]; /* File name */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Encrypted Casefolded entries require saving the hash on disk. This structure
|
|
||||||
* followed ext4_dir_entry_2's name[name_len] at the next 4 byte aligned
|
|
||||||
* boundary.
|
|
||||||
*/
|
|
||||||
struct ext4_dir_entry_hash {
|
|
||||||
__le32 hash;
|
|
||||||
__le32 minor_hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The new version of the directory entry. Since EXT4 structures are
|
* The new version of the directory entry. Since EXT4 structures are
|
||||||
* stored in intel byte order, and the name_len field could never be
|
* stored in intel byte order, and the name_len field could never be
|
||||||
@ -1992,22 +1981,6 @@ struct ext4_dir_entry_2 {
|
|||||||
char name[EXT4_NAME_LEN]; /* File name */
|
char name[EXT4_NAME_LEN]; /* File name */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Access the hashes at the end of ext4_dir_entry_2
|
|
||||||
*/
|
|
||||||
#define EXT4_DIRENT_HASHES(entry) \
|
|
||||||
((struct ext4_dir_entry_hash *) \
|
|
||||||
(((void *)(entry)) + \
|
|
||||||
((8 + (entry)->name_len + EXT4_DIR_ROUND) & ~EXT4_DIR_ROUND)))
|
|
||||||
#define EXT4_DIRENT_HASH(entry) le32_to_cpu(EXT4_DIRENT_HASHES(de)->hash)
|
|
||||||
#define EXT4_DIRENT_MINOR_HASH(entry) \
|
|
||||||
le32_to_cpu(EXT4_DIRENT_HASHES(de)->minor_hash)
|
|
||||||
|
|
||||||
static inline bool ext4_hash_in_dirent(const struct inode *inode)
|
|
||||||
{
|
|
||||||
return IS_CASEFOLDED(inode) && IS_ENCRYPTED(inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a bogus directory entry at the end of each leaf block that
|
* This is a bogus directory entry at the end of each leaf block that
|
||||||
* records checksums.
|
* records checksums.
|
||||||
@ -2049,24 +2022,10 @@ struct ext4_dir_entry_tail {
|
|||||||
*/
|
*/
|
||||||
#define EXT4_DIR_PAD 4
|
#define EXT4_DIR_PAD 4
|
||||||
#define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1)
|
#define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1)
|
||||||
|
#define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \
|
||||||
|
~EXT4_DIR_ROUND)
|
||||||
#define EXT4_MAX_REC_LEN ((1<<16)-1)
|
#define EXT4_MAX_REC_LEN ((1<<16)-1)
|
||||||
|
|
||||||
/*
|
|
||||||
* The rec_len is dependent on the type of directory. Directories that are
|
|
||||||
* casefolded and encrypted need to store the hash as well, so we add room for
|
|
||||||
* ext4_extended_dir_entry_2. For all entries related to '.' or '..' you should
|
|
||||||
* pass NULL for dir, as those entries do not use the extra fields.
|
|
||||||
*/
|
|
||||||
static inline unsigned int ext4_dir_rec_len(__u8 name_len,
|
|
||||||
const struct inode *dir)
|
|
||||||
{
|
|
||||||
int rec_len = (name_len + 8 + EXT4_DIR_ROUND);
|
|
||||||
|
|
||||||
if (dir && ext4_hash_in_dirent(dir))
|
|
||||||
rec_len += sizeof(struct ext4_dir_entry_hash);
|
|
||||||
return (rec_len & ~EXT4_DIR_ROUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we ever get support for fs block sizes > page_size, we'll need
|
* If we ever get support for fs block sizes > page_size, we'll need
|
||||||
* to remove the #if statements in the next two functions...
|
* to remove the #if statements in the next two functions...
|
||||||
@ -2123,7 +2082,6 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize)
|
|||||||
#define DX_HASH_LEGACY_UNSIGNED 3
|
#define DX_HASH_LEGACY_UNSIGNED 3
|
||||||
#define DX_HASH_HALF_MD4_UNSIGNED 4
|
#define DX_HASH_HALF_MD4_UNSIGNED 4
|
||||||
#define DX_HASH_TEA_UNSIGNED 5
|
#define DX_HASH_TEA_UNSIGNED 5
|
||||||
#define DX_HASH_SIPHASH 6
|
|
||||||
|
|
||||||
static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc,
|
static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc,
|
||||||
const void *address, unsigned int length)
|
const void *address, unsigned int length)
|
||||||
@ -2181,7 +2139,6 @@ struct ext4_filename {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define fname_name(p) ((p)->disk_name.name)
|
#define fname_name(p) ((p)->disk_name.name)
|
||||||
#define fname_usr_name(p) ((p)->usr_fname->name)
|
|
||||||
#define fname_len(p) ((p)->disk_name.len)
|
#define fname_len(p) ((p)->disk_name.len)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2516,22 +2473,21 @@ extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
|
|||||||
struct file *,
|
struct file *,
|
||||||
struct ext4_dir_entry_2 *,
|
struct ext4_dir_entry_2 *,
|
||||||
struct buffer_head *, char *, int,
|
struct buffer_head *, char *, int,
|
||||||
ext4_lblk_t, unsigned int);
|
unsigned int);
|
||||||
#define ext4_check_dir_entry(dir, filp, de, bh, buf, size, lblk, offset) \
|
#define ext4_check_dir_entry(dir, filp, de, bh, buf, size, offset) \
|
||||||
unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
|
unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
|
||||||
(de), (bh), (buf), (size), (lblk), (offset)))
|
(de), (bh), (buf), (size), (offset)))
|
||||||
extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
|
extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
|
||||||
__u32 minor_hash,
|
__u32 minor_hash,
|
||||||
struct ext4_dir_entry_2 *dirent,
|
struct ext4_dir_entry_2 *dirent,
|
||||||
struct fscrypt_str *ent_name);
|
struct fscrypt_str *ent_name);
|
||||||
extern void ext4_htree_free_dir_info(struct dir_private_info *p);
|
extern void ext4_htree_free_dir_info(struct dir_private_info *p);
|
||||||
extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
void *buf, int buf_size,
|
void *buf, int buf_size,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
struct ext4_dir_entry_2 **dest_de);
|
struct ext4_dir_entry_2 **dest_de);
|
||||||
void ext4_insert_dentry(struct inode *dir, struct inode *inode,
|
void ext4_insert_dentry(struct inode *inode,
|
||||||
struct ext4_dir_entry_2 *de,
|
struct ext4_dir_entry_2 *de,
|
||||||
int buf_size,
|
int buf_size,
|
||||||
struct ext4_filename *fname);
|
struct ext4_filename *fname);
|
||||||
@ -2717,12 +2673,11 @@ extern int ext4_search_dir(struct buffer_head *bh,
|
|||||||
int buf_size,
|
int buf_size,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
ext4_lblk_t lblk, unsigned int offset,
|
unsigned int offset,
|
||||||
struct ext4_dir_entry_2 **res_dir);
|
struct ext4_dir_entry_2 **res_dir);
|
||||||
extern int ext4_generic_delete_entry(handle_t *handle,
|
extern int ext4_generic_delete_entry(handle_t *handle,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct ext4_dir_entry_2 *de_del,
|
struct ext4_dir_entry_2 *de_del,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
void *entry_buf,
|
void *entry_buf,
|
||||||
int buf_size,
|
int buf_size,
|
||||||
@ -3248,6 +3203,9 @@ extern void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
|
|||||||
extern int ext4_handle_dirty_dirent_node(handle_t *handle,
|
extern int ext4_handle_dirty_dirent_node(handle_t *handle,
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
struct buffer_head *bh);
|
struct buffer_head *bh);
|
||||||
|
extern int ext4_ci_compare(const struct inode *parent,
|
||||||
|
const struct qstr *fname,
|
||||||
|
const struct qstr *entry, bool quick);
|
||||||
|
|
||||||
#define S_SHIFT 12
|
#define S_SHIFT 12
|
||||||
static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
|
static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
|
||||||
|
@ -201,7 +201,7 @@ static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
|
|||||||
* represented, and whether or not the returned hash is 32 bits or 64
|
* represented, and whether or not the returned hash is 32 bits or 64
|
||||||
* bits. 32 bit hashes will return 0 for the minor hash.
|
* bits. 32 bit hashes will return 0 for the minor hash.
|
||||||
*/
|
*/
|
||||||
static int __ext4fs_dirhash(const struct inode *dir, const char *name, int len,
|
static int __ext4fs_dirhash(const char *name, int len,
|
||||||
struct dx_hash_info *hinfo)
|
struct dx_hash_info *hinfo)
|
||||||
{
|
{
|
||||||
__u32 hash;
|
__u32 hash;
|
||||||
@ -261,22 +261,6 @@ static int __ext4fs_dirhash(const struct inode *dir, const char *name, int len,
|
|||||||
hash = buf[0];
|
hash = buf[0];
|
||||||
minor_hash = buf[1];
|
minor_hash = buf[1];
|
||||||
break;
|
break;
|
||||||
case DX_HASH_SIPHASH:
|
|
||||||
{
|
|
||||||
struct qstr qname = QSTR_INIT(name, len);
|
|
||||||
__u64 combined_hash;
|
|
||||||
|
|
||||||
if (fscrypt_has_encryption_key(dir)) {
|
|
||||||
combined_hash = fscrypt_fname_siphash(dir, &qname);
|
|
||||||
} else {
|
|
||||||
ext4_warning_inode(dir, "Siphash requires key");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash = (__u32)(combined_hash >> 32);
|
|
||||||
minor_hash = (__u32)combined_hash;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
hinfo->hash = 0;
|
hinfo->hash = 0;
|
||||||
return -1;
|
return -1;
|
||||||
@ -298,7 +282,7 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
|
|||||||
unsigned char *buff;
|
unsigned char *buff;
|
||||||
struct qstr qstr = {.name = name, .len = len };
|
struct qstr qstr = {.name = name, .len = len };
|
||||||
|
|
||||||
if (len && needs_casefold(dir) && um) {
|
if (len && IS_CASEFOLDED(dir) && um) {
|
||||||
buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
|
buff = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL);
|
||||||
if (!buff)
|
if (!buff)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -309,12 +293,12 @@ int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
|
|||||||
goto opaque_seq;
|
goto opaque_seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = __ext4fs_dirhash(dir, buff, dlen, hinfo);
|
r = __ext4fs_dirhash(buff, dlen, hinfo);
|
||||||
|
|
||||||
kfree(buff);
|
kfree(buff);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
opaque_seq:
|
opaque_seq:
|
||||||
#endif
|
#endif
|
||||||
return __ext4fs_dirhash(dir, name, len, hinfo);
|
return __ext4fs_dirhash(name, len, hinfo);
|
||||||
}
|
}
|
||||||
|
@ -463,10 +463,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (qstr) {
|
if (qstr) {
|
||||||
if (ext4_hash_in_dirent(parent))
|
hinfo.hash_version = DX_HASH_HALF_MD4;
|
||||||
hinfo.hash_version = DX_HASH_SIPHASH;
|
|
||||||
else
|
|
||||||
hinfo.hash_version = DX_HASH_HALF_MD4;
|
|
||||||
hinfo.seed = sbi->s_hash_seed;
|
hinfo.seed = sbi->s_hash_seed;
|
||||||
ext4fs_dirhash(parent, qstr->name, qstr->len, &hinfo);
|
ext4fs_dirhash(parent, qstr->name, qstr->len, &hinfo);
|
||||||
grp = hinfo.hash;
|
grp = hinfo.hash;
|
||||||
|
@ -1022,7 +1022,7 @@ void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,
|
|||||||
offset, de_len, de->name_len, de->name,
|
offset, de_len, de->name_len, de->name,
|
||||||
de->name_len, le32_to_cpu(de->inode));
|
de->name_len, le32_to_cpu(de->inode));
|
||||||
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
||||||
inline_start, inline_size, 0, offset))
|
inline_start, inline_size, offset))
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
offset += de_len;
|
offset += de_len;
|
||||||
@ -1048,7 +1048,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
|
|||||||
int err;
|
int err;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
|
|
||||||
err = ext4_find_dest_de(dir, inode, 0, iloc->bh, inline_start,
|
err = ext4_find_dest_de(dir, inode, iloc->bh, inline_start,
|
||||||
inline_size, fname, &de);
|
inline_size, fname, &de);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -1057,7 +1057,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
|
|||||||
err = ext4_journal_get_write_access(handle, iloc->bh);
|
err = ext4_journal_get_write_access(handle, iloc->bh);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ext4_insert_dentry(dir, inode, de, inline_size, fname);
|
ext4_insert_dentry(inode, de, inline_size, fname);
|
||||||
|
|
||||||
ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
|
ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
|
||||||
|
|
||||||
@ -1126,7 +1126,7 @@ static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,
|
|||||||
int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE;
|
int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE;
|
||||||
int new_size = get_max_inline_xattr_value_size(dir, iloc);
|
int new_size = get_max_inline_xattr_value_size(dir, iloc);
|
||||||
|
|
||||||
if (new_size - old_size <= ext4_dir_rec_len(1, NULL))
|
if (new_size - old_size <= EXT4_DIR_REC_LEN(1))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
ret = ext4_update_inline_data(handle, dir,
|
ret = ext4_update_inline_data(handle, dir,
|
||||||
@ -1415,8 +1415,8 @@ int htree_inlinedir_to_tree(struct file *dir_file,
|
|||||||
fake.name_len = 1;
|
fake.name_len = 1;
|
||||||
strcpy(fake.name, ".");
|
strcpy(fake.name, ".");
|
||||||
fake.rec_len = ext4_rec_len_to_disk(
|
fake.rec_len = ext4_rec_len_to_disk(
|
||||||
ext4_dir_rec_len(fake.name_len, NULL),
|
EXT4_DIR_REC_LEN(fake.name_len),
|
||||||
inline_size);
|
inline_size);
|
||||||
ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
|
ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
|
||||||
de = &fake;
|
de = &fake;
|
||||||
pos = EXT4_INLINE_DOTDOT_OFFSET;
|
pos = EXT4_INLINE_DOTDOT_OFFSET;
|
||||||
@ -1425,8 +1425,8 @@ int htree_inlinedir_to_tree(struct file *dir_file,
|
|||||||
fake.name_len = 2;
|
fake.name_len = 2;
|
||||||
strcpy(fake.name, "..");
|
strcpy(fake.name, "..");
|
||||||
fake.rec_len = ext4_rec_len_to_disk(
|
fake.rec_len = ext4_rec_len_to_disk(
|
||||||
ext4_dir_rec_len(fake.name_len, NULL),
|
EXT4_DIR_REC_LEN(fake.name_len),
|
||||||
inline_size);
|
inline_size);
|
||||||
ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
|
ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);
|
||||||
de = &fake;
|
de = &fake;
|
||||||
pos = EXT4_INLINE_DOTDOT_SIZE;
|
pos = EXT4_INLINE_DOTDOT_SIZE;
|
||||||
@ -1435,18 +1435,13 @@ int htree_inlinedir_to_tree(struct file *dir_file,
|
|||||||
pos += ext4_rec_len_from_disk(de->rec_len, inline_size);
|
pos += ext4_rec_len_from_disk(de->rec_len, inline_size);
|
||||||
if (ext4_check_dir_entry(inode, dir_file, de,
|
if (ext4_check_dir_entry(inode, dir_file, de,
|
||||||
iloc.bh, dir_buf,
|
iloc.bh, dir_buf,
|
||||||
inline_size, block, pos)) {
|
inline_size, pos)) {
|
||||||
ret = count;
|
ret = count;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext4_hash_in_dirent(dir)) {
|
ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
|
||||||
hinfo->hash = EXT4_DIRENT_HASH(de);
|
|
||||||
hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de);
|
|
||||||
} else {
|
|
||||||
ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
|
|
||||||
}
|
|
||||||
if ((hinfo->hash < start_hash) ||
|
if ((hinfo->hash < start_hash) ||
|
||||||
((hinfo->hash == start_hash) &&
|
((hinfo->hash == start_hash) &&
|
||||||
(hinfo->minor_hash < start_minor_hash)))
|
(hinfo->minor_hash < start_minor_hash)))
|
||||||
@ -1528,8 +1523,8 @@ int ext4_read_inline_dir(struct file *file,
|
|||||||
* So we will use extra_offset and extra_size to indicate them
|
* So we will use extra_offset and extra_size to indicate them
|
||||||
* during the inline dir iteration.
|
* during the inline dir iteration.
|
||||||
*/
|
*/
|
||||||
dotdot_offset = ext4_dir_rec_len(1, NULL);
|
dotdot_offset = EXT4_DIR_REC_LEN(1);
|
||||||
dotdot_size = dotdot_offset + ext4_dir_rec_len(2, NULL);
|
dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2);
|
||||||
extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;
|
extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;
|
||||||
extra_size = extra_offset + inline_size;
|
extra_size = extra_offset + inline_size;
|
||||||
|
|
||||||
@ -1564,7 +1559,7 @@ int ext4_read_inline_dir(struct file *file,
|
|||||||
* failure will be detected in the
|
* failure will be detected in the
|
||||||
* dirent test below. */
|
* dirent test below. */
|
||||||
if (ext4_rec_len_from_disk(de->rec_len, extra_size)
|
if (ext4_rec_len_from_disk(de->rec_len, extra_size)
|
||||||
< ext4_dir_rec_len(1, NULL))
|
< EXT4_DIR_REC_LEN(1))
|
||||||
break;
|
break;
|
||||||
i += ext4_rec_len_from_disk(de->rec_len,
|
i += ext4_rec_len_from_disk(de->rec_len,
|
||||||
extra_size);
|
extra_size);
|
||||||
@ -1592,7 +1587,7 @@ int ext4_read_inline_dir(struct file *file,
|
|||||||
de = (struct ext4_dir_entry_2 *)
|
de = (struct ext4_dir_entry_2 *)
|
||||||
(dir_buf + ctx->pos - extra_offset);
|
(dir_buf + ctx->pos - extra_offset);
|
||||||
if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf,
|
if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf,
|
||||||
extra_size, 0, ctx->pos))
|
extra_size, ctx->pos))
|
||||||
goto out;
|
goto out;
|
||||||
if (le32_to_cpu(de->inode)) {
|
if (le32_to_cpu(de->inode)) {
|
||||||
if (!dir_emit(ctx, de->name, de->name_len,
|
if (!dir_emit(ctx, de->name, de->name_len,
|
||||||
@ -1684,7 +1679,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
|
|||||||
EXT4_INLINE_DOTDOT_SIZE;
|
EXT4_INLINE_DOTDOT_SIZE;
|
||||||
inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
|
inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
|
||||||
ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
|
ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
|
||||||
dir, fname, 0, 0, res_dir);
|
dir, fname, 0, res_dir);
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
goto out_find;
|
goto out_find;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1697,7 +1692,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
|
|||||||
inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;
|
inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;
|
||||||
|
|
||||||
ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
|
ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
|
||||||
dir, fname, 0, 0, res_dir);
|
dir, fname, 0, res_dir);
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
goto out_find;
|
goto out_find;
|
||||||
|
|
||||||
@ -1746,7 +1741,7 @@ int ext4_delete_inline_entry(handle_t *handle,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = ext4_generic_delete_entry(handle, dir, de_del, 0, bh,
|
err = ext4_generic_delete_entry(handle, dir, de_del, bh,
|
||||||
inline_start, inline_size, 0);
|
inline_start, inline_size, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1830,7 +1825,7 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
|
|||||||
&inline_pos, &inline_size);
|
&inline_pos, &inline_size);
|
||||||
if (ext4_check_dir_entry(dir, NULL, de,
|
if (ext4_check_dir_entry(dir, NULL, de,
|
||||||
iloc.bh, inline_pos,
|
iloc.bh, inline_pos,
|
||||||
inline_size, 0, offset)) {
|
inline_size, offset)) {
|
||||||
ext4_warning(dir->i_sb,
|
ext4_warning(dir->i_sb,
|
||||||
"bad inline directory (dir #%lu) - "
|
"bad inline directory (dir #%lu) - "
|
||||||
"inode %u, rec_len %u, name_len %d"
|
"inode %u, rec_len %u, name_len %d"
|
||||||
|
310
fs/ext4/namei.c
310
fs/ext4/namei.c
@ -276,11 +276,9 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
|
|||||||
unsigned blocksize, struct dx_hash_info *hinfo,
|
unsigned blocksize, struct dx_hash_info *hinfo,
|
||||||
struct dx_map_entry map[]);
|
struct dx_map_entry map[]);
|
||||||
static void dx_sort_map(struct dx_map_entry *map, unsigned count);
|
static void dx_sort_map(struct dx_map_entry *map, unsigned count);
|
||||||
static struct ext4_dir_entry_2 *dx_move_dirents(struct inode *dir, char *from,
|
static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to,
|
||||||
char *to, struct dx_map_entry *offsets,
|
struct dx_map_entry *offsets, int count, unsigned blocksize);
|
||||||
int count, unsigned int blocksize);
|
static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize);
|
||||||
static struct ext4_dir_entry_2 *dx_pack_dirents(struct inode *dir, char *base,
|
|
||||||
unsigned int blocksize);
|
|
||||||
static void dx_insert_block(struct dx_frame *frame,
|
static void dx_insert_block(struct dx_frame *frame,
|
||||||
u32 hash, ext4_lblk_t block);
|
u32 hash, ext4_lblk_t block);
|
||||||
static int ext4_htree_next_block(struct inode *dir, __u32 hash,
|
static int ext4_htree_next_block(struct inode *dir, __u32 hash,
|
||||||
@ -289,7 +287,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
|
|||||||
__u32 *start_hash);
|
__u32 *start_hash);
|
||||||
static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
struct ext4_dir_entry_2 **res_dir, ext4_lblk_t *lblk);
|
struct ext4_dir_entry_2 **res_dir);
|
||||||
static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
|
static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
|
||||||
struct inode *dir, struct inode *inode);
|
struct inode *dir, struct inode *inode);
|
||||||
|
|
||||||
@ -571,9 +569,8 @@ static inline void dx_set_limit(struct dx_entry *entries, unsigned value)
|
|||||||
|
|
||||||
static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
|
static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
|
||||||
{
|
{
|
||||||
unsigned int entry_space = dir->i_sb->s_blocksize -
|
unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
|
||||||
ext4_dir_rec_len(1, NULL) -
|
EXT4_DIR_REC_LEN(2) - infosize;
|
||||||
ext4_dir_rec_len(2, NULL) - infosize;
|
|
||||||
|
|
||||||
if (ext4_has_metadata_csum(dir->i_sb))
|
if (ext4_has_metadata_csum(dir->i_sb))
|
||||||
entry_space -= sizeof(struct dx_tail);
|
entry_space -= sizeof(struct dx_tail);
|
||||||
@ -582,8 +579,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
|
|||||||
|
|
||||||
static inline unsigned dx_node_limit(struct inode *dir)
|
static inline unsigned dx_node_limit(struct inode *dir)
|
||||||
{
|
{
|
||||||
unsigned int entry_space = dir->i_sb->s_blocksize -
|
unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
|
||||||
ext4_dir_rec_len(0, dir);
|
|
||||||
|
|
||||||
if (ext4_has_metadata_csum(dir->i_sb))
|
if (ext4_has_metadata_csum(dir->i_sb))
|
||||||
entry_space -= sizeof(struct dx_tail);
|
entry_space -= sizeof(struct dx_tail);
|
||||||
@ -679,10 +675,7 @@ static struct stats dx_show_leaf(struct inode *dir,
|
|||||||
name = fname_crypto_str.name;
|
name = fname_crypto_str.name;
|
||||||
len = fname_crypto_str.len;
|
len = fname_crypto_str.len;
|
||||||
}
|
}
|
||||||
if (IS_CASEFOLDED(dir))
|
ext4fs_dirhash(dir, de->name,
|
||||||
h.hash = EXT4_DIRENT_HASH(de);
|
|
||||||
else
|
|
||||||
ext4fs_dirhash(dir, de->name,
|
|
||||||
de->name_len, &h);
|
de->name_len, &h);
|
||||||
printk("%*.s:(E)%x.%u ", len, name,
|
printk("%*.s:(E)%x.%u ", len, name,
|
||||||
h.hash, (unsigned) ((char *) de
|
h.hash, (unsigned) ((char *) de
|
||||||
@ -698,7 +691,7 @@ static struct stats dx_show_leaf(struct inode *dir,
|
|||||||
(unsigned) ((char *) de - base));
|
(unsigned) ((char *) de - base));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
space += ext4_dir_rec_len(de->name_len, dir);
|
space += EXT4_DIR_REC_LEN(de->name_len);
|
||||||
names++;
|
names++;
|
||||||
}
|
}
|
||||||
de = ext4_next_entry(de, size);
|
de = ext4_next_entry(de, size);
|
||||||
@ -772,25 +765,11 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
|
|||||||
root = (struct dx_root *) frame->bh->b_data;
|
root = (struct dx_root *) frame->bh->b_data;
|
||||||
if (root->info.hash_version != DX_HASH_TEA &&
|
if (root->info.hash_version != DX_HASH_TEA &&
|
||||||
root->info.hash_version != DX_HASH_HALF_MD4 &&
|
root->info.hash_version != DX_HASH_HALF_MD4 &&
|
||||||
root->info.hash_version != DX_HASH_LEGACY &&
|
root->info.hash_version != DX_HASH_LEGACY) {
|
||||||
root->info.hash_version != DX_HASH_SIPHASH) {
|
|
||||||
ext4_warning_inode(dir, "Unrecognised inode hash code %u",
|
ext4_warning_inode(dir, "Unrecognised inode hash code %u",
|
||||||
root->info.hash_version);
|
root->info.hash_version);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (ext4_hash_in_dirent(dir)) {
|
|
||||||
if (root->info.hash_version != DX_HASH_SIPHASH) {
|
|
||||||
ext4_warning_inode(dir,
|
|
||||||
"Hash in dirent, but hash is not SIPHASH");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (root->info.hash_version == DX_HASH_SIPHASH) {
|
|
||||||
ext4_warning_inode(dir,
|
|
||||||
"Hash code is SIPHASH, but hash not in dirent");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fname)
|
if (fname)
|
||||||
hinfo = &fname->hinfo;
|
hinfo = &fname->hinfo;
|
||||||
hinfo->hash_version = root->info.hash_version;
|
hinfo->hash_version = root->info.hash_version;
|
||||||
@ -1026,7 +1005,6 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
|||||||
struct ext4_dir_entry_2 *de, *top;
|
struct ext4_dir_entry_2 *de, *top;
|
||||||
int err = 0, count = 0;
|
int err = 0, count = 0;
|
||||||
struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0), tmp_str;
|
struct fscrypt_str fname_crypto_str = FSTR_INIT(NULL, 0), tmp_str;
|
||||||
int csum = ext4_has_metadata_csum(dir->i_sb);
|
|
||||||
|
|
||||||
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
|
dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n",
|
||||||
(unsigned long)block));
|
(unsigned long)block));
|
||||||
@ -1035,11 +1013,9 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
|||||||
return PTR_ERR(bh);
|
return PTR_ERR(bh);
|
||||||
|
|
||||||
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
||||||
/* csum entries are not larger in the casefolded encrypted case */
|
|
||||||
top = (struct ext4_dir_entry_2 *) ((char *) de +
|
top = (struct ext4_dir_entry_2 *) ((char *) de +
|
||||||
dir->i_sb->s_blocksize -
|
dir->i_sb->s_blocksize -
|
||||||
ext4_dir_rec_len(0,
|
EXT4_DIR_REC_LEN(0));
|
||||||
csum ? NULL : dir));
|
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
#ifdef CONFIG_FS_ENCRYPTION
|
||||||
/* Check if the directory is encrypted */
|
/* Check if the directory is encrypted */
|
||||||
if (IS_ENCRYPTED(dir)) {
|
if (IS_ENCRYPTED(dir)) {
|
||||||
@ -1058,23 +1034,13 @@ static int htree_dirblock_to_tree(struct file *dir_file,
|
|||||||
#endif
|
#endif
|
||||||
for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
|
for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
|
||||||
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
||||||
bh->b_data, bh->b_size, block,
|
bh->b_data, bh->b_size,
|
||||||
(block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
|
(block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
|
||||||
+ ((char *)de - bh->b_data))) {
|
+ ((char *)de - bh->b_data))) {
|
||||||
/* silently ignore the rest of the block */
|
/* silently ignore the rest of the block */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ext4_hash_in_dirent(dir)) {
|
ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
|
||||||
if (de->name_len && de->inode) {
|
|
||||||
hinfo->hash = EXT4_DIRENT_HASH(de);
|
|
||||||
hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de);
|
|
||||||
} else {
|
|
||||||
hinfo->hash = 0;
|
|
||||||
hinfo->minor_hash = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
|
|
||||||
}
|
|
||||||
if ((hinfo->hash < start_hash) ||
|
if ((hinfo->hash < start_hash) ||
|
||||||
((hinfo->hash == start_hash) &&
|
((hinfo->hash == start_hash) &&
|
||||||
(hinfo->minor_hash < start_minor_hash)))
|
(hinfo->minor_hash < start_minor_hash)))
|
||||||
@ -1145,11 +1111,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
|
|||||||
start_hash, start_minor_hash));
|
start_hash, start_minor_hash));
|
||||||
dir = file_inode(dir_file);
|
dir = file_inode(dir_file);
|
||||||
if (!(ext4_test_inode_flag(dir, EXT4_INODE_INDEX))) {
|
if (!(ext4_test_inode_flag(dir, EXT4_INODE_INDEX))) {
|
||||||
if (ext4_hash_in_dirent(dir))
|
hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
|
||||||
hinfo.hash_version = DX_HASH_SIPHASH;
|
|
||||||
else
|
|
||||||
hinfo.hash_version =
|
|
||||||
EXT4_SB(dir->i_sb)->s_def_hash_version;
|
|
||||||
if (hinfo.hash_version <= DX_HASH_TEA)
|
if (hinfo.hash_version <= DX_HASH_TEA)
|
||||||
hinfo.hash_version +=
|
hinfo.hash_version +=
|
||||||
EXT4_SB(dir->i_sb)->s_hash_unsigned;
|
EXT4_SB(dir->i_sb)->s_hash_unsigned;
|
||||||
@ -1242,12 +1204,11 @@ errout:
|
|||||||
static inline int search_dirblock(struct buffer_head *bh,
|
static inline int search_dirblock(struct buffer_head *bh,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
unsigned int offset,
|
unsigned int offset,
|
||||||
struct ext4_dir_entry_2 **res_dir)
|
struct ext4_dir_entry_2 **res_dir)
|
||||||
{
|
{
|
||||||
return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir,
|
return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir,
|
||||||
fname, lblk, offset, res_dir);
|
fname, offset, res_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1268,10 +1229,7 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
|
|||||||
|
|
||||||
while ((char *) de < base + blocksize) {
|
while ((char *) de < base + blocksize) {
|
||||||
if (de->name_len && de->inode) {
|
if (de->name_len && de->inode) {
|
||||||
if (ext4_hash_in_dirent(dir))
|
ext4fs_dirhash(dir, de->name, de->name_len, &h);
|
||||||
h.hash = EXT4_DIRENT_HASH(de);
|
|
||||||
else
|
|
||||||
ext4fs_dirhash(dir, de->name, de->name_len, &h);
|
|
||||||
map_tail--;
|
map_tail--;
|
||||||
map_tail->hash = h.hash;
|
map_tail->hash = h.hash;
|
||||||
map_tail->offs = ((char *) de - base)>>2;
|
map_tail->offs = ((char *) de - base)>>2;
|
||||||
@ -1335,47 +1293,31 @@ static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block)
|
|||||||
* Returns: 0 if the directory entry matches, more than 0 if it
|
* Returns: 0 if the directory entry matches, more than 0 if it
|
||||||
* doesn't match or less than zero on error.
|
* doesn't match or less than zero on error.
|
||||||
*/
|
*/
|
||||||
static int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
|
int ext4_ci_compare(const struct inode *parent, const struct qstr *name,
|
||||||
u8 *de_name, size_t de_name_len, bool quick)
|
const struct qstr *entry, bool quick)
|
||||||
{
|
{
|
||||||
const struct super_block *sb = parent->i_sb;
|
const struct super_block *sb = parent->i_sb;
|
||||||
const struct unicode_map *um = sb->s_encoding;
|
const struct unicode_map *um = sb->s_encoding;
|
||||||
struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len);
|
|
||||||
struct qstr entry = QSTR_INIT(de_name, de_name_len);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (IS_ENCRYPTED(parent)) {
|
|
||||||
const struct fscrypt_str encrypted_name =
|
|
||||||
FSTR_INIT(de_name, de_name_len);
|
|
||||||
|
|
||||||
decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL);
|
|
||||||
if (!decrypted_name.name)
|
|
||||||
return -ENOMEM;
|
|
||||||
ret = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name,
|
|
||||||
&decrypted_name);
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
entry.name = decrypted_name.name;
|
|
||||||
entry.len = decrypted_name.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quick)
|
if (quick)
|
||||||
ret = utf8_strncasecmp_folded(um, name, &entry);
|
ret = utf8_strncasecmp_folded(um, name, entry);
|
||||||
else
|
else
|
||||||
ret = utf8_strncasecmp(um, name, &entry);
|
ret = utf8_strncasecmp(um, name, entry);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* Handle invalid character sequence as either an error
|
/* Handle invalid character sequence as either an error
|
||||||
* or as an opaque byte sequence.
|
* or as an opaque byte sequence.
|
||||||
*/
|
*/
|
||||||
if (sb_has_enc_strict_mode(sb))
|
if (sb_has_enc_strict_mode(sb))
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
else if (name->len != entry.len)
|
|
||||||
ret = 1;
|
if (name->len != entry->len)
|
||||||
else
|
return 1;
|
||||||
ret = !!memcmp(name->name, entry.name, entry.len);
|
|
||||||
|
return !!memcmp(name->name, entry->name, name->len);
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
kfree(decrypted_name.name);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1411,11 +1353,14 @@ void ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
|
|||||||
*
|
*
|
||||||
* Return: %true if the directory entry matches, otherwise %false.
|
* Return: %true if the directory entry matches, otherwise %false.
|
||||||
*/
|
*/
|
||||||
static bool ext4_match(struct inode *parent,
|
static inline bool ext4_match(const struct inode *parent,
|
||||||
const struct ext4_filename *fname,
|
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;
|
||||||
|
#ifdef CONFIG_UNICODE
|
||||||
|
const struct qstr entry = {.name = de->name, .len = de->name_len};
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!de->inode)
|
if (!de->inode)
|
||||||
return false;
|
return false;
|
||||||
@ -1431,23 +1376,10 @@ static bool ext4_match(struct inode *parent,
|
|||||||
if (fname->cf_name.name) {
|
if (fname->cf_name.name) {
|
||||||
struct qstr cf = {.name = fname->cf_name.name,
|
struct qstr cf = {.name = fname->cf_name.name,
|
||||||
.len = fname->cf_name.len};
|
.len = fname->cf_name.len};
|
||||||
if (IS_ENCRYPTED(parent)) {
|
return !ext4_ci_compare(parent, &cf, &entry, true);
|
||||||
struct dx_hash_info hinfo;
|
|
||||||
|
|
||||||
hinfo.hash_version = DX_HASH_SIPHASH;
|
|
||||||
hinfo.seed = NULL;
|
|
||||||
ext4fs_dirhash(parent, fname->cf_name.name,
|
|
||||||
fname_len(fname), &hinfo);
|
|
||||||
if (hinfo.hash != EXT4_DIRENT_HASH(de) ||
|
|
||||||
hinfo.minor_hash !=
|
|
||||||
EXT4_DIRENT_MINOR_HASH(de))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return !ext4_ci_compare(parent, &cf, de->name,
|
|
||||||
de->name_len, true);
|
|
||||||
}
|
}
|
||||||
return !ext4_ci_compare(parent, fname->usr_fname, de->name,
|
return !ext4_ci_compare(parent, fname->usr_fname, &entry,
|
||||||
de->name_len, false);
|
false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1459,8 +1391,7 @@ static bool ext4_match(struct inode *parent,
|
|||||||
*/
|
*/
|
||||||
int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
|
int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
|
||||||
struct inode *dir, struct ext4_filename *fname,
|
struct inode *dir, struct ext4_filename *fname,
|
||||||
ext4_lblk_t lblk, unsigned int offset,
|
unsigned int offset, struct ext4_dir_entry_2 **res_dir)
|
||||||
struct ext4_dir_entry_2 **res_dir)
|
|
||||||
{
|
{
|
||||||
struct ext4_dir_entry_2 * de;
|
struct ext4_dir_entry_2 * de;
|
||||||
char * dlimit;
|
char * dlimit;
|
||||||
@ -1476,7 +1407,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
|
|||||||
/* 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, search_buf,
|
if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf,
|
||||||
buf_size, lblk, offset))
|
buf_size, offset))
|
||||||
return -1;
|
return -1;
|
||||||
*res_dir = de;
|
*res_dir = de;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1522,7 +1453,7 @@ static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block,
|
|||||||
static struct buffer_head *__ext4_find_entry(struct inode *dir,
|
static struct buffer_head *__ext4_find_entry(struct inode *dir,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
struct ext4_dir_entry_2 **res_dir,
|
struct ext4_dir_entry_2 **res_dir,
|
||||||
int *inlined, ext4_lblk_t *lblk)
|
int *inlined)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct buffer_head *bh_use[NAMEI_RA_SIZE];
|
struct buffer_head *bh_use[NAMEI_RA_SIZE];
|
||||||
@ -1546,8 +1477,6 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
|
|||||||
int has_inline_data = 1;
|
int has_inline_data = 1;
|
||||||
ret = ext4_find_inline_entry(dir, fname, res_dir,
|
ret = ext4_find_inline_entry(dir, fname, res_dir,
|
||||||
&has_inline_data);
|
&has_inline_data);
|
||||||
if (lblk)
|
|
||||||
*lblk = 0;
|
|
||||||
if (has_inline_data) {
|
if (has_inline_data) {
|
||||||
if (inlined)
|
if (inlined)
|
||||||
*inlined = 1;
|
*inlined = 1;
|
||||||
@ -1566,7 +1495,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
|
|||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
if (is_dx(dir)) {
|
if (is_dx(dir)) {
|
||||||
ret = ext4_dx_find_entry(dir, fname, res_dir, lblk);
|
ret = ext4_dx_find_entry(dir, fname, res_dir);
|
||||||
/*
|
/*
|
||||||
* On success, or if the error was file not found,
|
* On success, or if the error was file not found,
|
||||||
* return. Otherwise, fall back to doing a search the
|
* return. Otherwise, fall back to doing a search the
|
||||||
@ -1631,11 +1560,9 @@ restart:
|
|||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
}
|
}
|
||||||
set_buffer_verified(bh);
|
set_buffer_verified(bh);
|
||||||
i = search_dirblock(bh, dir, fname, block,
|
i = search_dirblock(bh, dir, fname,
|
||||||
block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
|
block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
if (lblk)
|
|
||||||
*lblk = block;
|
|
||||||
EXT4_I(dir)->i_dir_start_lookup = block;
|
EXT4_I(dir)->i_dir_start_lookup = block;
|
||||||
ret = bh;
|
ret = bh;
|
||||||
goto cleanup_and_exit;
|
goto cleanup_and_exit;
|
||||||
@ -1670,7 +1597,7 @@ cleanup_and_exit:
|
|||||||
static struct buffer_head *ext4_find_entry(struct inode *dir,
|
static struct buffer_head *ext4_find_entry(struct inode *dir,
|
||||||
const struct qstr *d_name,
|
const struct qstr *d_name,
|
||||||
struct ext4_dir_entry_2 **res_dir,
|
struct ext4_dir_entry_2 **res_dir,
|
||||||
int *inlined, ext4_lblk_t *lblk)
|
int *inlined)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct ext4_filename fname;
|
struct ext4_filename fname;
|
||||||
@ -1682,7 +1609,7 @@ static struct buffer_head *ext4_find_entry(struct inode *dir,
|
|||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
bh = __ext4_find_entry(dir, &fname, res_dir, inlined, lblk);
|
bh = __ext4_find_entry(dir, &fname, res_dir, inlined);
|
||||||
|
|
||||||
ext4_fname_free_filename(&fname);
|
ext4_fname_free_filename(&fname);
|
||||||
return bh;
|
return bh;
|
||||||
@ -1703,7 +1630,7 @@ static struct buffer_head *ext4_lookup_entry(struct inode *dir,
|
|||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
bh = __ext4_find_entry(dir, &fname, res_dir, NULL, NULL);
|
bh = __ext4_find_entry(dir, &fname, res_dir, NULL);
|
||||||
|
|
||||||
ext4_fname_free_filename(&fname);
|
ext4_fname_free_filename(&fname);
|
||||||
return bh;
|
return bh;
|
||||||
@ -1711,7 +1638,7 @@ static struct buffer_head *ext4_lookup_entry(struct inode *dir,
|
|||||||
|
|
||||||
static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
struct ext4_dir_entry_2 **res_dir, ext4_lblk_t *lblk)
|
struct ext4_dir_entry_2 **res_dir)
|
||||||
{
|
{
|
||||||
struct super_block * sb = dir->i_sb;
|
struct super_block * sb = dir->i_sb;
|
||||||
struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
|
struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
|
||||||
@ -1727,13 +1654,11 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
|
|||||||
return (struct buffer_head *) frame;
|
return (struct buffer_head *) frame;
|
||||||
do {
|
do {
|
||||||
block = dx_get_block(frame->at);
|
block = dx_get_block(frame->at);
|
||||||
if (lblk)
|
|
||||||
*lblk = block;
|
|
||||||
bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
|
bh = ext4_read_dirblock(dir, block, DIRENT_HTREE);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
retval = search_dirblock(bh, dir, fname, block,
|
retval = search_dirblock(bh, dir, fname,
|
||||||
block << EXT4_BLOCK_SIZE_BITS(sb),
|
block << EXT4_BLOCK_SIZE_BITS(sb),
|
||||||
res_dir);
|
res_dir);
|
||||||
if (retval == 1)
|
if (retval == 1)
|
||||||
@ -1828,7 +1753,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
|
|||||||
struct ext4_dir_entry_2 * de;
|
struct ext4_dir_entry_2 * de;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
|
||||||
bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL, NULL);
|
bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return (struct dentry *) bh;
|
return (struct dentry *) bh;
|
||||||
if (!bh)
|
if (!bh)
|
||||||
@ -1850,8 +1775,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
|
|||||||
* Returns pointer to last entry moved.
|
* Returns pointer to last entry moved.
|
||||||
*/
|
*/
|
||||||
static struct ext4_dir_entry_2 *
|
static struct ext4_dir_entry_2 *
|
||||||
dx_move_dirents(struct inode *dir, char *from, char *to,
|
dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count,
|
||||||
struct dx_map_entry *map, int count,
|
|
||||||
unsigned blocksize)
|
unsigned blocksize)
|
||||||
{
|
{
|
||||||
unsigned rec_len = 0;
|
unsigned rec_len = 0;
|
||||||
@ -1859,8 +1783,7 @@ dx_move_dirents(struct inode *dir, char *from, char *to,
|
|||||||
while (count--) {
|
while (count--) {
|
||||||
struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *)
|
struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *)
|
||||||
(from + (map->offs<<2));
|
(from + (map->offs<<2));
|
||||||
rec_len = ext4_dir_rec_len(de->name_len, dir);
|
rec_len = EXT4_DIR_REC_LEN(de->name_len);
|
||||||
|
|
||||||
memcpy (to, de, rec_len);
|
memcpy (to, de, rec_len);
|
||||||
((struct ext4_dir_entry_2 *) to)->rec_len =
|
((struct ext4_dir_entry_2 *) to)->rec_len =
|
||||||
ext4_rec_len_to_disk(rec_len, blocksize);
|
ext4_rec_len_to_disk(rec_len, blocksize);
|
||||||
@ -1875,8 +1798,7 @@ dx_move_dirents(struct inode *dir, char *from, char *to,
|
|||||||
* Compact each dir entry in the range to the minimal rec_len.
|
* Compact each dir entry in the range to the minimal rec_len.
|
||||||
* Returns pointer to last entry in range.
|
* Returns pointer to last entry in range.
|
||||||
*/
|
*/
|
||||||
static struct ext4_dir_entry_2 *dx_pack_dirents(struct inode *dir, char *base,
|
static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
|
||||||
unsigned int blocksize)
|
|
||||||
{
|
{
|
||||||
struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
|
struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
|
||||||
unsigned rec_len = 0;
|
unsigned rec_len = 0;
|
||||||
@ -1885,7 +1807,7 @@ static struct ext4_dir_entry_2 *dx_pack_dirents(struct inode *dir, char *base,
|
|||||||
while ((char*)de < base + blocksize) {
|
while ((char*)de < base + blocksize) {
|
||||||
next = ext4_next_entry(de, blocksize);
|
next = ext4_next_entry(de, blocksize);
|
||||||
if (de->inode && de->name_len) {
|
if (de->inode && de->name_len) {
|
||||||
rec_len = ext4_dir_rec_len(de->name_len, dir);
|
rec_len = EXT4_DIR_REC_LEN(de->name_len);
|
||||||
if (de > to)
|
if (de > to)
|
||||||
memmove(to, de, rec_len);
|
memmove(to, de, rec_len);
|
||||||
to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize);
|
to->rec_len = ext4_rec_len_to_disk(rec_len, blocksize);
|
||||||
@ -1903,12 +1825,13 @@ static struct ext4_dir_entry_2 *dx_pack_dirents(struct inode *dir, char *base,
|
|||||||
* Returns pointer to de in block into which the new entry will be inserted.
|
* Returns pointer to de in block into which the new entry will be inserted.
|
||||||
*/
|
*/
|
||||||
static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
||||||
struct buffer_head **bh, struct dx_frame *frame,
|
struct buffer_head **bh,struct dx_frame *frame,
|
||||||
struct dx_hash_info *hinfo, ext4_lblk_t *newblock)
|
struct dx_hash_info *hinfo)
|
||||||
{
|
{
|
||||||
unsigned blocksize = dir->i_sb->s_blocksize;
|
unsigned blocksize = dir->i_sb->s_blocksize;
|
||||||
unsigned count, continued;
|
unsigned count, continued;
|
||||||
struct buffer_head *bh2;
|
struct buffer_head *bh2;
|
||||||
|
ext4_lblk_t newblock;
|
||||||
u32 hash2;
|
u32 hash2;
|
||||||
struct dx_map_entry *map;
|
struct dx_map_entry *map;
|
||||||
char *data1 = (*bh)->b_data, *data2;
|
char *data1 = (*bh)->b_data, *data2;
|
||||||
@ -1921,7 +1844,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
|||||||
if (ext4_has_metadata_csum(dir->i_sb))
|
if (ext4_has_metadata_csum(dir->i_sb))
|
||||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||||
|
|
||||||
bh2 = ext4_append(handle, dir, newblock);
|
bh2 = ext4_append(handle, dir, &newblock);
|
||||||
if (IS_ERR(bh2)) {
|
if (IS_ERR(bh2)) {
|
||||||
brelse(*bh);
|
brelse(*bh);
|
||||||
*bh = NULL;
|
*bh = NULL;
|
||||||
@ -1975,9 +1898,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
|||||||
hash2, split, count-split));
|
hash2, split, count-split));
|
||||||
|
|
||||||
/* Fancy dance to stay within two buffers */
|
/* Fancy dance to stay within two buffers */
|
||||||
de2 = dx_move_dirents(dir, data1, data2, map + split, count - split,
|
de2 = dx_move_dirents(data1, data2, map + split, count - split,
|
||||||
blocksize);
|
blocksize);
|
||||||
de = dx_pack_dirents(dir, data1, blocksize);
|
de = dx_pack_dirents(data1, blocksize);
|
||||||
de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
|
de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
|
||||||
(char *) de,
|
(char *) de,
|
||||||
blocksize);
|
blocksize);
|
||||||
@ -2002,7 +1925,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
|
|||||||
swap(*bh, bh2);
|
swap(*bh, bh2);
|
||||||
de = de2;
|
de = de2;
|
||||||
}
|
}
|
||||||
dx_insert_block(frame, hash2 + continued, *newblock);
|
dx_insert_block(frame, hash2 + continued, newblock);
|
||||||
err = ext4_handle_dirty_dirent_node(handle, dir, bh2);
|
err = ext4_handle_dirty_dirent_node(handle, dir, bh2);
|
||||||
if (err)
|
if (err)
|
||||||
goto journal_error;
|
goto journal_error;
|
||||||
@ -2022,14 +1945,13 @@ journal_error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
void *buf, int buf_size,
|
void *buf, int buf_size,
|
||||||
struct ext4_filename *fname,
|
struct ext4_filename *fname,
|
||||||
struct ext4_dir_entry_2 **dest_de)
|
struct ext4_dir_entry_2 **dest_de)
|
||||||
{
|
{
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
unsigned short reclen = ext4_dir_rec_len(fname_len(fname), dir);
|
unsigned short reclen = EXT4_DIR_REC_LEN(fname_len(fname));
|
||||||
int nlen, rlen;
|
int nlen, rlen;
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
char *top;
|
char *top;
|
||||||
@ -2038,11 +1960,11 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
|||||||
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, lblk, offset))
|
buf, buf_size, offset))
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
if (ext4_match(dir, fname, de))
|
if (ext4_match(dir, fname, de))
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
nlen = ext4_dir_rec_len(de->name_len, dir);
|
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)
|
||||||
break;
|
break;
|
||||||
@ -2056,8 +1978,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ext4_insert_dentry(struct inode *dir,
|
void ext4_insert_dentry(struct inode *inode,
|
||||||
struct inode *inode,
|
|
||||||
struct ext4_dir_entry_2 *de,
|
struct ext4_dir_entry_2 *de,
|
||||||
int buf_size,
|
int buf_size,
|
||||||
struct ext4_filename *fname)
|
struct ext4_filename *fname)
|
||||||
@ -2065,7 +1986,7 @@ void ext4_insert_dentry(struct inode *dir,
|
|||||||
|
|
||||||
int nlen, rlen;
|
int nlen, rlen;
|
||||||
|
|
||||||
nlen = ext4_dir_rec_len(de->name_len, dir);
|
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) {
|
if (de->inode) {
|
||||||
struct ext4_dir_entry_2 *de1 =
|
struct ext4_dir_entry_2 *de1 =
|
||||||
@ -2079,17 +2000,6 @@ void ext4_insert_dentry(struct inode *dir,
|
|||||||
ext4_set_de_type(inode->i_sb, de, inode->i_mode);
|
ext4_set_de_type(inode->i_sb, de, inode->i_mode);
|
||||||
de->name_len = fname_len(fname);
|
de->name_len = fname_len(fname);
|
||||||
memcpy(de->name, fname_name(fname), fname_len(fname));
|
memcpy(de->name, fname_name(fname), fname_len(fname));
|
||||||
if (ext4_hash_in_dirent(dir)) {
|
|
||||||
struct dx_hash_info hinfo;
|
|
||||||
|
|
||||||
hinfo.hash_version = DX_HASH_SIPHASH;
|
|
||||||
hinfo.seed = NULL;
|
|
||||||
ext4fs_dirhash(dir, fname_usr_name(fname),
|
|
||||||
fname_len(fname), &hinfo);
|
|
||||||
EXT4_DIRENT_HASHES(de)->hash = cpu_to_le32(hinfo.hash);
|
|
||||||
EXT4_DIRENT_HASHES(de)->minor_hash =
|
|
||||||
cpu_to_le32(hinfo.minor_hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2103,7 +2013,6 @@ void ext4_insert_dentry(struct inode *dir,
|
|||||||
static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct inode *inode, struct ext4_dir_entry_2 *de,
|
struct inode *inode, struct ext4_dir_entry_2 *de,
|
||||||
ext4_lblk_t blk,
|
|
||||||
struct buffer_head *bh)
|
struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
unsigned int blocksize = dir->i_sb->s_blocksize;
|
unsigned int blocksize = dir->i_sb->s_blocksize;
|
||||||
@ -2114,7 +2023,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
|||||||
csum_size = sizeof(struct ext4_dir_entry_tail);
|
csum_size = sizeof(struct ext4_dir_entry_tail);
|
||||||
|
|
||||||
if (!de) {
|
if (!de) {
|
||||||
err = ext4_find_dest_de(dir, inode, blk, bh, bh->b_data,
|
err = ext4_find_dest_de(dir, inode, bh, bh->b_data,
|
||||||
blocksize - csum_size, fname, &de);
|
blocksize - csum_size, fname, &de);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -2127,7 +2036,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* By now the buffer is marked for journaling */
|
/* By now the buffer is marked for journaling */
|
||||||
ext4_insert_dentry(dir, inode, de, blocksize, fname);
|
ext4_insert_dentry(inode, de, blocksize, fname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX shouldn't update any times until successful
|
* XXX shouldn't update any times until successful
|
||||||
@ -2223,16 +2132,11 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
|
|||||||
|
|
||||||
/* Initialize the root; the dot dirents already exist */
|
/* Initialize the root; the dot dirents already exist */
|
||||||
de = (struct ext4_dir_entry_2 *) (&root->dotdot);
|
de = (struct ext4_dir_entry_2 *) (&root->dotdot);
|
||||||
de->rec_len = ext4_rec_len_to_disk(
|
de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2),
|
||||||
blocksize - ext4_dir_rec_len(2, NULL), blocksize);
|
blocksize);
|
||||||
memset (&root->info, 0, sizeof(root->info));
|
memset (&root->info, 0, sizeof(root->info));
|
||||||
root->info.info_length = sizeof(root->info);
|
root->info.info_length = sizeof(root->info);
|
||||||
if (ext4_hash_in_dirent(dir))
|
root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
|
||||||
root->info.hash_version = DX_HASH_SIPHASH;
|
|
||||||
else
|
|
||||||
root->info.hash_version =
|
|
||||||
EXT4_SB(dir->i_sb)->s_def_hash_version;
|
|
||||||
|
|
||||||
entries = root->entries;
|
entries = root->entries;
|
||||||
dx_set_block(entries, 1);
|
dx_set_block(entries, 1);
|
||||||
dx_set_count(entries, 1);
|
dx_set_count(entries, 1);
|
||||||
@ -2243,12 +2147,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
|
|||||||
if (fname->hinfo.hash_version <= DX_HASH_TEA)
|
if (fname->hinfo.hash_version <= DX_HASH_TEA)
|
||||||
fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
|
fname->hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
|
||||||
fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
|
fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
|
||||||
if (ext4_hash_in_dirent(dir))
|
ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), &fname->hinfo);
|
||||||
ext4fs_dirhash(dir, fname_usr_name(fname),
|
|
||||||
fname_len(fname), &fname->hinfo);
|
|
||||||
else
|
|
||||||
ext4fs_dirhash(dir, fname_name(fname),
|
|
||||||
fname_len(fname), &fname->hinfo);
|
|
||||||
|
|
||||||
memset(frames, 0, sizeof(frames));
|
memset(frames, 0, sizeof(frames));
|
||||||
frame = frames;
|
frame = frames;
|
||||||
@ -2263,13 +2162,13 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
|
|||||||
if (retval)
|
if (retval)
|
||||||
goto out_frames;
|
goto out_frames;
|
||||||
|
|
||||||
de = do_split(handle, dir, &bh2, frame, &fname->hinfo, &block);
|
de = do_split(handle,dir, &bh2, frame, &fname->hinfo);
|
||||||
if (IS_ERR(de)) {
|
if (IS_ERR(de)) {
|
||||||
retval = PTR_ERR(de);
|
retval = PTR_ERR(de);
|
||||||
goto out_frames;
|
goto out_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = add_dirent_to_buf(handle, fname, dir, inode, de, block, bh2);
|
retval = add_dirent_to_buf(handle, fname, dir, inode, de, bh2);
|
||||||
out_frames:
|
out_frames:
|
||||||
/*
|
/*
|
||||||
* Even if the block split failed, we have to properly write
|
* Even if the block split failed, we have to properly write
|
||||||
@ -2365,7 +2264,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
retval = add_dirent_to_buf(handle, &fname, dir, inode,
|
retval = add_dirent_to_buf(handle, &fname, dir, inode,
|
||||||
NULL, block, bh);
|
NULL, bh);
|
||||||
if (retval != -ENOSPC)
|
if (retval != -ENOSPC)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2394,7 +2293,7 @@ add_to_new_block:
|
|||||||
initialize_dirent_tail(t, blocksize);
|
initialize_dirent_tail(t, blocksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = add_dirent_to_buf(handle, &fname, dir, inode, de, block, bh);
|
retval = add_dirent_to_buf(handle, &fname, dir, inode, de, bh);
|
||||||
out:
|
out:
|
||||||
ext4_fname_free_filename(&fname);
|
ext4_fname_free_filename(&fname);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
@ -2416,7 +2315,6 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
|
|||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
int restart;
|
int restart;
|
||||||
int err;
|
int err;
|
||||||
ext4_lblk_t lblk;
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
restart = 0;
|
restart = 0;
|
||||||
@ -2425,8 +2323,7 @@ again:
|
|||||||
return PTR_ERR(frame);
|
return PTR_ERR(frame);
|
||||||
entries = frame->entries;
|
entries = frame->entries;
|
||||||
at = frame->at;
|
at = frame->at;
|
||||||
lblk = dx_get_block(frame->at);
|
bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT_HTREE);
|
||||||
bh = ext4_read_dirblock(dir, lblk, DIRENT_HTREE);
|
|
||||||
if (IS_ERR(bh)) {
|
if (IS_ERR(bh)) {
|
||||||
err = PTR_ERR(bh);
|
err = PTR_ERR(bh);
|
||||||
bh = NULL;
|
bh = NULL;
|
||||||
@ -2438,7 +2335,7 @@ again:
|
|||||||
if (err)
|
if (err)
|
||||||
goto journal_error;
|
goto journal_error;
|
||||||
|
|
||||||
err = add_dirent_to_buf(handle, fname, dir, inode, NULL, lblk, bh);
|
err = add_dirent_to_buf(handle, fname, dir, inode, NULL, bh);
|
||||||
if (err != -ENOSPC)
|
if (err != -ENOSPC)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -2557,12 +2454,12 @@ again:
|
|||||||
goto journal_error;
|
goto journal_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
de = do_split(handle, dir, &bh, frame, &fname->hinfo, &lblk);
|
de = do_split(handle, dir, &bh, frame, &fname->hinfo);
|
||||||
if (IS_ERR(de)) {
|
if (IS_ERR(de)) {
|
||||||
err = PTR_ERR(de);
|
err = PTR_ERR(de);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
err = add_dirent_to_buf(handle, fname, dir, inode, de, lblk, bh);
|
err = add_dirent_to_buf(handle, fname, dir, inode, de, bh);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
journal_error:
|
journal_error:
|
||||||
@ -2585,7 +2482,6 @@ cleanup:
|
|||||||
int ext4_generic_delete_entry(handle_t *handle,
|
int ext4_generic_delete_entry(handle_t *handle,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct ext4_dir_entry_2 *de_del,
|
struct ext4_dir_entry_2 *de_del,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
void *entry_buf,
|
void *entry_buf,
|
||||||
int buf_size,
|
int buf_size,
|
||||||
@ -2600,7 +2496,7 @@ int ext4_generic_delete_entry(handle_t *handle,
|
|||||||
de = (struct ext4_dir_entry_2 *)entry_buf;
|
de = (struct ext4_dir_entry_2 *)entry_buf;
|
||||||
while (i < buf_size - csum_size) {
|
while (i < buf_size - csum_size) {
|
||||||
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
if (ext4_check_dir_entry(dir, NULL, de, bh,
|
||||||
entry_buf, buf_size, lblk, i))
|
entry_buf, buf_size, i))
|
||||||
return -EFSCORRUPTED;
|
return -EFSCORRUPTED;
|
||||||
if (de == de_del) {
|
if (de == de_del) {
|
||||||
if (pde)
|
if (pde)
|
||||||
@ -2625,7 +2521,6 @@ int ext4_generic_delete_entry(handle_t *handle,
|
|||||||
static int ext4_delete_entry(handle_t *handle,
|
static int ext4_delete_entry(handle_t *handle,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct ext4_dir_entry_2 *de_del,
|
struct ext4_dir_entry_2 *de_del,
|
||||||
ext4_lblk_t lblk,
|
|
||||||
struct buffer_head *bh)
|
struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
int err, csum_size = 0;
|
int err, csum_size = 0;
|
||||||
@ -2646,7 +2541,7 @@ static int ext4_delete_entry(handle_t *handle,
|
|||||||
if (unlikely(err))
|
if (unlikely(err))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = ext4_generic_delete_entry(handle, dir, de_del, lblk,
|
err = ext4_generic_delete_entry(handle, dir, de_del,
|
||||||
bh, bh->b_data,
|
bh, bh->b_data,
|
||||||
dir->i_sb->s_blocksize, csum_size);
|
dir->i_sb->s_blocksize, csum_size);
|
||||||
if (err)
|
if (err)
|
||||||
@ -2829,7 +2724,7 @@ struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
|
|||||||
{
|
{
|
||||||
de->inode = cpu_to_le32(inode->i_ino);
|
de->inode = cpu_to_le32(inode->i_ino);
|
||||||
de->name_len = 1;
|
de->name_len = 1;
|
||||||
de->rec_len = ext4_rec_len_to_disk(ext4_dir_rec_len(de->name_len, NULL),
|
de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len),
|
||||||
blocksize);
|
blocksize);
|
||||||
strcpy(de->name, ".");
|
strcpy(de->name, ".");
|
||||||
ext4_set_de_type(inode->i_sb, de, S_IFDIR);
|
ext4_set_de_type(inode->i_sb, de, S_IFDIR);
|
||||||
@ -2839,12 +2734,11 @@ struct ext4_dir_entry_2 *ext4_init_dot_dotdot(struct inode *inode,
|
|||||||
de->name_len = 2;
|
de->name_len = 2;
|
||||||
if (!dotdot_real_len)
|
if (!dotdot_real_len)
|
||||||
de->rec_len = ext4_rec_len_to_disk(blocksize -
|
de->rec_len = ext4_rec_len_to_disk(blocksize -
|
||||||
(csum_size + ext4_dir_rec_len(1, NULL)),
|
(csum_size + EXT4_DIR_REC_LEN(1)),
|
||||||
blocksize);
|
blocksize);
|
||||||
else
|
else
|
||||||
de->rec_len = ext4_rec_len_to_disk(
|
de->rec_len = ext4_rec_len_to_disk(
|
||||||
ext4_dir_rec_len(de->name_len, NULL),
|
EXT4_DIR_REC_LEN(de->name_len), blocksize);
|
||||||
blocksize);
|
|
||||||
strcpy(de->name, "..");
|
strcpy(de->name, "..");
|
||||||
ext4_set_de_type(inode->i_sb, de, S_IFDIR);
|
ext4_set_de_type(inode->i_sb, de, S_IFDIR);
|
||||||
|
|
||||||
@ -2972,8 +2866,7 @@ bool ext4_empty_dir(struct inode *inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sb = inode->i_sb;
|
sb = inode->i_sb;
|
||||||
if (inode->i_size < ext4_dir_rec_len(1, NULL) +
|
if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2)) {
|
||||||
ext4_dir_rec_len(2, NULL)) {
|
|
||||||
EXT4_ERROR_INODE(inode, "invalid size");
|
EXT4_ERROR_INODE(inode, "invalid size");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2985,7 +2878,7 @@ bool ext4_empty_dir(struct inode *inode)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
||||||
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 0,
|
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
|
||||||
0) ||
|
0) ||
|
||||||
le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
|
le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
|
||||||
ext4_warning_inode(inode, "directory missing '.'");
|
ext4_warning_inode(inode, "directory missing '.'");
|
||||||
@ -2994,7 +2887,7 @@ bool ext4_empty_dir(struct inode *inode)
|
|||||||
}
|
}
|
||||||
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
|
||||||
de = ext4_next_entry(de, sb->s_blocksize);
|
de = ext4_next_entry(de, sb->s_blocksize);
|
||||||
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 0,
|
if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
|
||||||
offset) ||
|
offset) ||
|
||||||
le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
|
le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
|
||||||
ext4_warning_inode(inode, "directory missing '..'");
|
ext4_warning_inode(inode, "directory missing '..'");
|
||||||
@ -3018,7 +2911,7 @@ bool ext4_empty_dir(struct inode *inode)
|
|||||||
de = (struct ext4_dir_entry_2 *) (bh->b_data +
|
de = (struct ext4_dir_entry_2 *) (bh->b_data +
|
||||||
(offset & (sb->s_blocksize - 1)));
|
(offset & (sb->s_blocksize - 1)));
|
||||||
if (ext4_check_dir_entry(inode, NULL, de, bh,
|
if (ext4_check_dir_entry(inode, NULL, de, bh,
|
||||||
bh->b_data, bh->b_size, 0, offset)) {
|
bh->b_data, bh->b_size, offset)) {
|
||||||
offset = (offset | (sb->s_blocksize - 1)) + 1;
|
offset = (offset | (sb->s_blocksize - 1)) + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3213,8 +3106,6 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
handle_t *handle = NULL;
|
handle_t *handle = NULL;
|
||||||
ext4_lblk_t lblk;
|
|
||||||
|
|
||||||
|
|
||||||
if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
|
if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -3229,7 +3120,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, &lblk);
|
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return PTR_ERR(bh);
|
return PTR_ERR(bh);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
@ -3256,7 +3147,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
retval = ext4_delete_entry(handle, dir, de, lblk, bh);
|
retval = ext4_delete_entry(handle, dir, de, bh);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto end_rmdir;
|
goto end_rmdir;
|
||||||
if (!EXT4_DIR_LINK_EMPTY(inode))
|
if (!EXT4_DIR_LINK_EMPTY(inode))
|
||||||
@ -3302,7 +3193,6 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
handle_t *handle = NULL;
|
handle_t *handle = NULL;
|
||||||
ext4_lblk_t lblk;
|
|
||||||
|
|
||||||
if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
|
if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -3318,7 +3208,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = -ENOENT;
|
retval = -ENOENT;
|
||||||
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, &lblk);
|
bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return PTR_ERR(bh);
|
return PTR_ERR(bh);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
@ -3341,7 +3231,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
if (IS_DIRSYNC(dir))
|
if (IS_DIRSYNC(dir))
|
||||||
ext4_handle_sync(handle);
|
ext4_handle_sync(handle);
|
||||||
|
|
||||||
retval = ext4_delete_entry(handle, dir, de, lblk, bh);
|
retval = ext4_delete_entry(handle, dir, de, bh);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto end_unlink;
|
goto end_unlink;
|
||||||
dir->i_ctime = dir->i_mtime = current_time(dir);
|
dir->i_ctime = dir->i_mtime = current_time(dir);
|
||||||
@ -3603,7 +3493,6 @@ struct ext4_renament {
|
|||||||
int dir_nlink_delta;
|
int dir_nlink_delta;
|
||||||
|
|
||||||
/* entry for "dentry" */
|
/* entry for "dentry" */
|
||||||
ext4_lblk_t lblk;
|
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
int inlined;
|
int inlined;
|
||||||
@ -3696,7 +3585,7 @@ static void ext4_resetent(handle_t *handle, struct ext4_renament *ent,
|
|||||||
* so the old->de may no longer valid and need to find it again
|
* so the old->de may no longer valid and need to find it again
|
||||||
* before reset old inode info.
|
* before reset old inode info.
|
||||||
*/
|
*/
|
||||||
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL, NULL);
|
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
|
||||||
if (IS_ERR(old.bh))
|
if (IS_ERR(old.bh))
|
||||||
retval = PTR_ERR(old.bh);
|
retval = PTR_ERR(old.bh);
|
||||||
if (!old.bh)
|
if (!old.bh)
|
||||||
@ -3716,13 +3605,12 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
|
|||||||
int retval = -ENOENT;
|
int retval = -ENOENT;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
ext4_lblk_t lblk;
|
|
||||||
|
|
||||||
bh = ext4_find_entry(dir, d_name, &de, NULL, &lblk);
|
bh = ext4_find_entry(dir, d_name, &de, NULL);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return PTR_ERR(bh);
|
return PTR_ERR(bh);
|
||||||
if (bh) {
|
if (bh) {
|
||||||
retval = ext4_delete_entry(handle, dir, de, lblk, bh);
|
retval = ext4_delete_entry(handle, dir, de, bh);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@ -3746,8 +3634,7 @@ static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent,
|
|||||||
retval = ext4_find_delete_entry(handle, ent->dir,
|
retval = ext4_find_delete_entry(handle, ent->dir,
|
||||||
&ent->dentry->d_name);
|
&ent->dentry->d_name);
|
||||||
} else {
|
} else {
|
||||||
retval = ext4_delete_entry(handle, ent->dir, ent->de,
|
retval = ext4_delete_entry(handle, ent->dir, ent->de, ent->bh);
|
||||||
ent->lblk, ent->bh);
|
|
||||||
if (retval == -ENOENT) {
|
if (retval == -ENOENT) {
|
||||||
retval = ext4_find_delete_entry(handle, ent->dir,
|
retval = ext4_find_delete_entry(handle, ent->dir,
|
||||||
&ent->dentry->d_name);
|
&ent->dentry->d_name);
|
||||||
@ -3860,8 +3747,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL,
|
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
|
||||||
&old.lblk);
|
|
||||||
if (IS_ERR(old.bh))
|
if (IS_ERR(old.bh))
|
||||||
return PTR_ERR(old.bh);
|
return PTR_ERR(old.bh);
|
||||||
/*
|
/*
|
||||||
@ -3875,7 +3761,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
goto release_bh;
|
goto release_bh;
|
||||||
|
|
||||||
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
||||||
&new.de, &new.inlined, NULL);
|
&new.de, &new.inlined);
|
||||||
if (IS_ERR(new.bh)) {
|
if (IS_ERR(new.bh)) {
|
||||||
retval = PTR_ERR(new.bh);
|
retval = PTR_ERR(new.bh);
|
||||||
new.bh = NULL;
|
new.bh = NULL;
|
||||||
@ -4059,7 +3945,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
|
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
|
||||||
&old.de, &old.inlined, NULL);
|
&old.de, &old.inlined);
|
||||||
if (IS_ERR(old.bh))
|
if (IS_ERR(old.bh))
|
||||||
return PTR_ERR(old.bh);
|
return PTR_ERR(old.bh);
|
||||||
/*
|
/*
|
||||||
@ -4073,7 +3959,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
goto end_rename;
|
goto end_rename;
|
||||||
|
|
||||||
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
||||||
&new.de, &new.inlined, NULL);
|
&new.de, &new.inlined);
|
||||||
if (IS_ERR(new.bh)) {
|
if (IS_ERR(new.bh)) {
|
||||||
retval = PTR_ERR(new.bh);
|
retval = PTR_ERR(new.bh);
|
||||||
new.bh = NULL;
|
new.bh = NULL;
|
||||||
|
@ -3890,6 +3890,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
struct unicode_map *encoding;
|
struct unicode_map *encoding;
|
||||||
__u16 encoding_flags;
|
__u16 encoding_flags;
|
||||||
|
|
||||||
|
if (ext4_has_feature_encrypt(sb)) {
|
||||||
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
"Can't mount with encoding and encryption");
|
||||||
|
goto failed_mount;
|
||||||
|
}
|
||||||
|
|
||||||
if (ext4_sb_read_encoding(es, &encoding_info,
|
if (ext4_sb_read_encoding(es, &encoding_info,
|
||||||
&encoding_flags)) {
|
&encoding_flags)) {
|
||||||
ext4_msg(sb, KERN_ERR,
|
ext4_msg(sb, KERN_ERR,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user