Fix directory blocks checksum updating logic.

Count dirent tail in the searchslot logic in case of directory block search.
Add htree root csum update function call in case of rename.
This commit is contained in:
Fedor Uporov 2018-08-21 18:39:02 +00:00
parent a5207d3ef6
commit e49d64a7a7
4 changed files with 37 additions and 17 deletions

View File

@ -162,12 +162,32 @@ ext2_init_dirent_tail(struct ext2fs_direct_tail *tp)
tp->e2dt_reserved_ft = EXT2_FT_DIR_CSUM;
}
int
ext2_is_dirent_tail(struct inode *ip, struct ext2fs_direct_2 *ep)
{
struct m_ext2fs *fs;
struct ext2fs_direct_tail *tp;
fs = ip->i_e2fs;
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
return (0);
tp = (struct ext2fs_direct_tail *)ep;
if (tp->e2dt_reserved_zero1 == 0 &&
tp->e2dt_rec_len == sizeof(struct ext2fs_direct_tail) &&
tp->e2dt_reserved_zero2 == 0 &&
tp->e2dt_reserved_ft == EXT2_FT_DIR_CSUM)
return (1);
return (0);
}
struct ext2fs_direct_tail *
ext2_dirent_get_tail(struct inode *ip, struct ext2fs_direct_2 *ep)
{
struct ext2fs_direct_2 *dep;
void *top;
struct ext2fs_direct_tail *tp;
unsigned int rec_len;
dep = ep;
@ -184,14 +204,10 @@ ext2_dirent_get_tail(struct inode *ip, struct ext2fs_direct_2 *ep)
if (dep != top)
return (NULL);
tp = (struct ext2fs_direct_tail *)dep;
if (tp->e2dt_reserved_zero1 ||
tp->e2dt_rec_len != sizeof(struct ext2fs_direct_tail) ||
tp->e2dt_reserved_zero2 ||
tp->e2dt_reserved_ft != EXT2_FT_DIR_CSUM)
return (NULL);
if (ext2_is_dirent_tail(ip, dep))
return ((struct ext2fs_direct_tail *)dep);
return (tp);
return (NULL);
}
static uint32_t

View File

@ -120,6 +120,7 @@ int ext2_dx_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep);
int ext2_extent_blk_csum_verify(struct inode *, void *);
void ext2_extent_blk_csum_set(struct inode *, void *);
void ext2_init_dirent_tail(struct ext2fs_direct_tail *);
int ext2_is_dirent_tail(struct inode *, struct ext2fs_direct_2 *);
int ext2_gd_i_bitmap_csum_verify(struct m_ext2fs *, int, struct buf *);
void ext2_gd_i_bitmap_csum_set(struct m_ext2fs *, int, struct buf *);
int ext2_gd_b_bitmap_csum_verify(struct m_ext2fs *, int, struct buf *);

View File

@ -429,16 +429,13 @@ ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp
error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp);
if (error != 0)
return (error);
entryoffsetinblock = 0;
/*
* If still looking for a slot, and at a DIRBLKSIZE
* boundary, have to start looking for free space again.
*/
if (ss.slotstatus == NONE &&
(entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
if (ss.slotstatus == NONE) {
ss.slotoffset = -1;
ss.slotfreespace = 0;
}
error = ext2_search_dirblock(dp, bp->b_data, &entry_found,
cnp->cn_nameptr, cnp->cn_namelen,
&entryoffsetinblock, &i_offset, &prevoff,
@ -719,9 +716,7 @@ ext2_search_dirblock(struct inode *ip, void *data, int *foundp,
vdp = ITOV(ip);
ep = (struct ext2fs_direct_2 *)((char *)data + offset);
top = (struct ext2fs_direct_2 *)((char *)data +
bsize - EXT2_DIR_REC_LEN(0));
top = (struct ext2fs_direct_2 *)((char *)data + bsize);
while (ep < top) {
/*
* Full validation checks are slow, so we only check
@ -751,6 +746,8 @@ ext2_search_dirblock(struct inode *ip, void *data, int *foundp,
if (ep->e2d_ino != 0)
size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
else if (ext2_is_dirent_tail(ip, ep))
size -= sizeof(struct ext2fs_direct_tail);
if (size > 0) {
if (size >= ssp->slotneeded) {
ssp->slotstatus = FOUND;

View File

@ -1081,8 +1081,14 @@ ext2_rename(struct vop_rename_args *ap)
"rename: mangled dir");
} else {
dirbuf->dotdot_ino = newparent;
/*
* dirblock 0 could be htree root,
* try both csum update functions.
*/
ext2_dirent_csum_set(ip,
(struct ext2fs_direct_2 *)dirbuf);
ext2_dx_csum_set(ip,
(struct ext2fs_direct_2 *)dirbuf);
(void)vn_rdwr(UIO_WRITE, fvp,
(caddr_t)dirbuf,
ip->i_e2fs->e2fs_bsize,