Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163712721
D15396.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D15396.diff
View Options
Index: head/sys/fs/ext2fs/ext2_csum.c
===================================================================
--- head/sys/fs/ext2fs/ext2_csum.c
+++ head/sys/fs/ext2fs/ext2_csum.c
@@ -154,12 +154,37 @@
header->h_checksum = ext2_extattr_blk_csum(ip, ip->i_facl, header);
}
-static struct ext2fs_direct_tail *
-ext2_get_dirent_tail(struct inode *ip, struct ext2fs_direct_2 *ep)
+void
+ext2_init_dirent_tail(struct ext2fs_direct_tail *tp)
{
+ memset(tp, 0, sizeof(struct ext2fs_direct_tail));
+ tp->e2dt_rec_len = sizeof(struct ext2fs_direct_tail);
+ tp->e2dt_reserved_ft = EXT2_FT_DIR_CSUM;
+}
+
+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;
- tp = EXT2_DIRENT_TAIL(ep, ip->i_e2fs->e2fs_bsize);
+ dep = ep;
+ top = EXT2_DIRENT_TAIL(ep, ip->i_e2fs->e2fs_bsize);
+ rec_len = dep->e2d_reclen;
+
+ while (rec_len && !(rec_len & 0x3)) {
+ dep = (struct ext2fs_direct_2 *)(((char *)dep) + rec_len);
+ if ((void *)dep >= top)
+ break;
+ rec_len = dep->e2d_reclen;
+ }
+
+ 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 ||
@@ -189,13 +214,13 @@
return (crc);
}
-static int
+int
ext2_dirent_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep)
{
uint32_t calculated;
struct ext2fs_direct_tail *tp;
- tp = ext2_get_dirent_tail(ip, ep);
+ tp = ext2_dirent_get_tail(ip, ep);
if (tp == NULL)
return (0);
@@ -263,7 +288,7 @@
return (crc);
}
-static int
+int
ext2_dx_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep)
{
uint32_t calculated;
@@ -304,7 +329,7 @@
ep = (struct ext2fs_direct_2 *)bp->b_data;
- if (ext2_get_dirent_tail(ip, ep) != NULL)
+ if (ext2_dirent_get_tail(ip, ep) != NULL)
error = ext2_dirent_csum_verify(ip, ep);
else if (ext2_get_dx_count(ip, ep, NULL) != NULL)
error = ext2_dx_csum_verify(ip, ep);
@@ -316,12 +341,18 @@
return (error);
}
-static void
+void
ext2_dirent_csum_set(struct inode *ip, struct ext2fs_direct_2 *ep)
{
+ struct m_ext2fs *fs;
struct ext2fs_direct_tail *tp;
- tp = ext2_get_dirent_tail(ip, ep);
+ fs = ip->i_e2fs;
+
+ if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
+ return;
+
+ tp = ext2_dirent_get_tail(ip, ep);
if (tp == NULL)
return;
@@ -329,13 +360,19 @@
ext2_dirent_csum(ip, ep, (char *)tp - (char *)ep);
}
-static void
+void
ext2_dx_csum_set(struct inode *ip, struct ext2fs_direct_2 *ep)
{
+ struct m_ext2fs *fs;
struct ext2fs_htree_count *cp;
struct ext2fs_htree_tail *tp;
int count_offset, limit, count;
+ fs = ip->i_e2fs;
+
+ if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
+ return;
+
cp = ext2_get_dx_count(ip, ep, &count_offset);
if (cp == NULL)
return;
@@ -350,35 +387,6 @@
tp->ht_checksum = ext2_dx_csum(ip, ep, count_offset, count, tp);
}
-void
-ext2_dir_blk_csum_set_mem(struct inode *ip, char *buf, int size)
-{
- struct m_ext2fs *fs;
- struct ext2fs_direct_2 *ep;
-
- fs = ip->i_e2fs;
-
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
- return;
-
- ep = (struct ext2fs_direct_2 *)buf;
-
- if (ext2_htree_has_idx(ip)) {
- if (ext2_get_dx_count(ip, ep, NULL) != NULL)
- ext2_dx_csum_set(ip, ep);
- } else {
- if (ext2_get_dirent_tail(ip, ep) != NULL)
- ext2_dirent_csum_set(ip, ep);
- }
-}
-
-void
-ext2_dir_blk_csum_set(struct inode *ip, struct buf *bp)
-{
-
- ext2_dir_blk_csum_set_mem(ip, bp->b_data, bp->b_bufsize);
-}
-
static uint32_t
ext2_extent_blk_csum(struct inode *ip, struct ext4_extent_header *ehp)
{
@@ -543,9 +551,9 @@
offset = offsetof(struct ext2fs_dinode, e2di_chksum_lo);
csum_size = sizeof(dummy_csum);
inum = ip->i_number;
- gen = ip->i_gen;
crc = calculate_crc32c(fs->e2fs_csum_seed,
(uint8_t *)&inum, sizeof(inum));
+ gen = ip->i_gen;
inode_csum_seed = calculate_crc32c(crc,
(uint8_t *)&gen, sizeof(gen));
Index: head/sys/fs/ext2fs/ext2_extern.h
===================================================================
--- head/sys/fs/ext2fs/ext2_extern.h
+++ head/sys/fs/ext2fs/ext2_extern.h
@@ -43,6 +43,7 @@
struct ext2fs_dinode;
struct ext2fs_direct_2;
+struct ext2fs_direct_tail;
struct ext2fs_searchslot;
struct indir;
struct inode;
@@ -110,10 +111,15 @@
int ext2_extattr_blk_csum_verify(struct inode *, struct buf *);
void ext2_extattr_blk_csum_set(struct inode *, struct buf *);
int ext2_dir_blk_csum_verify(struct inode *, struct buf *);
-void ext2_dir_blk_csum_set(struct inode *, struct buf *);
-void ext2_dir_blk_csum_set_mem(struct inode *, char *, int);
+struct ext2fs_direct_tail *ext2_dirent_get_tail(struct inode *ip,
+ struct ext2fs_direct_2 *ep);
+void ext2_dirent_csum_set(struct inode *, struct ext2fs_direct_2 *);
+int ext2_dirent_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep);
+void ext2_dx_csum_set(struct inode *, struct ext2fs_direct_2 *);
+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_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 *);
@@ -122,7 +128,6 @@
void ext2_ei_csum_set(struct inode *, struct ext2fs_dinode *);
int ext2_gd_csum_verify(struct m_ext2fs *, struct cdev *);
void ext2_gd_csum_set(struct m_ext2fs *);
-
/* Flags to low-level allocation routines.
* The low 16-bits are reserved for IO_ flags from vnode.h.
Index: head/sys/fs/ext2fs/ext2_htree.c
===================================================================
--- head/sys/fs/ext2fs/ext2_htree.c
+++ head/sys/fs/ext2fs/ext2_htree.c
@@ -56,7 +56,7 @@
static void ext2_append_entry(char *block, uint32_t blksize,
struct ext2fs_direct_2 *last_entry,
- struct ext2fs_direct_2 *new_entry);
+ struct ext2fs_direct_2 *new_entry, int csum_size);
static int ext2_htree_append_block(struct vnode *vp, char *data,
struct componentname *cnp, uint32_t blksize);
static int ext2_htree_check_next(struct inode *ip, uint32_t hash,
@@ -82,12 +82,14 @@
uint32_t hash);
static void ext2_htree_set_limit(struct ext2fs_htree_entry *ep,
uint16_t limit);
-static int ext2_htree_split_dirblock(char *block1, char *block2,
- uint32_t blksize, uint32_t *hash_seed, uint8_t hash_version,
+static int ext2_htree_split_dirblock(struct inode *ip,
+ char *block1, char *block2, uint32_t blksize,
+ uint32_t *hash_seed, uint8_t hash_version,
uint32_t *split_hash, struct ext2fs_direct_2 *entry);
static void ext2_htree_release(struct ext2fs_htree_lookup_info *info);
static uint32_t ext2_htree_root_limit(struct inode *ip, int len);
-static int ext2_htree_writebuf(struct ext2fs_htree_lookup_info *info);
+static int ext2_htree_writebuf(struct inode *ip,
+ struct ext2fs_htree_lookup_info *info);
int
ext2_htree_has_idx(struct inode *ip)
@@ -207,10 +209,16 @@
static uint32_t
ext2_htree_root_limit(struct inode *ip, int len)
{
+ struct m_ext2fs *fs;
uint32_t space;
+ fs = ip->i_e2fs;
space = ip->i_e2fs->e2fs_bsize - EXT2_DIR_REC_LEN(1) -
EXT2_DIR_REC_LEN(2) - len;
+
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
+ space -= sizeof(struct ext2fs_htree_tail);
+
return (space / sizeof(struct ext2fs_htree_entry));
}
@@ -223,6 +231,9 @@
fs = ip->i_e2fs;
space = fs->e2fs_bsize - EXT2_DIR_REC_LEN(0);
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
+ space -= sizeof(struct ext2fs_htree_tail);
+
return (space / sizeof(struct ext2fs_htree_entry));
}
@@ -417,13 +428,13 @@
}
static int
-ext2_htree_writebuf(struct ext2fs_htree_lookup_info *info)
+ext2_htree_writebuf(struct inode* ip, struct ext2fs_htree_lookup_info *info)
{
int i, error;
for (i = 0; i < info->h_levels_num; i++) {
struct buf *bp = info->h_levels[i].h_bp;
-
+ ext2_dx_csum_set(ip, (struct ext2fs_direct_2 *)bp->b_data);
error = bwrite(bp);
if (error)
return (error);
@@ -487,14 +498,14 @@
static void
ext2_append_entry(char *block, uint32_t blksize,
struct ext2fs_direct_2 *last_entry,
- struct ext2fs_direct_2 *new_entry)
+ struct ext2fs_direct_2 *new_entry, int csum_size)
{
uint16_t entry_len;
entry_len = EXT2_DIR_REC_LEN(last_entry->e2d_namlen);
last_entry->e2d_reclen = entry_len;
last_entry = (struct ext2fs_direct_2 *)((char *)last_entry + entry_len);
- new_entry->e2d_reclen = block + blksize - (char *)last_entry;
+ new_entry->e2d_reclen = block + blksize - (char *)last_entry - csum_size;
memcpy(last_entry, new_entry, EXT2_DIR_REC_LEN(new_entry->e2d_namlen));
}
@@ -502,12 +513,13 @@
* Move half of entries from the old directory block to the new one.
*/
static int
-ext2_htree_split_dirblock(char *block1, char *block2, uint32_t blksize,
- uint32_t *hash_seed, uint8_t hash_version,
+ext2_htree_split_dirblock(struct inode *ip, char *block1, char *block2,
+ uint32_t blksize, uint32_t *hash_seed, uint8_t hash_version,
uint32_t *split_hash, struct ext2fs_direct_2 *entry)
{
+ struct m_ext2fs *fs;
int entry_cnt = 0;
- int size = 0;
+ int size = 0, csum_size = 0;
int i, k;
uint32_t offset;
uint16_t entry_len = 0;
@@ -516,11 +528,15 @@
char *dest;
struct ext2fs_htree_sort_entry *sort_info;
+ fs = ip->i_e2fs;
ep = (struct ext2fs_direct_2 *)block1;
dest = block2;
sort_info = (struct ext2fs_htree_sort_entry *)
((char *)block2 + blksize);
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
+ csum_size = sizeof(struct ext2fs_direct_tail);
+
/*
* Calculate name hash value for the entry which is to be added.
*/
@@ -530,7 +546,7 @@
/*
* Fill in directory entry sort descriptors.
*/
- while ((char *)ep < block1 + blksize) {
+ while ((char *)ep < block1 + blksize - csum_size) {
if (ep->e2d_ino && ep->e2d_namlen) {
entry_cnt++;
sort_info--;
@@ -585,7 +601,7 @@
/* Shrink directory entries in block 1. */
last = (struct ext2fs_direct_2 *)block1;
entry_len = 0;
- for (offset = 0; offset < blksize; ) {
+ for (offset = 0; offset < blksize - csum_size; ) {
ep = (struct ext2fs_direct_2 *)(block1 + offset);
offset += ep->e2d_reclen;
if (ep->e2d_ino) {
@@ -600,19 +616,24 @@
if (entry_hash >= *split_hash) {
/* Add entry to block 2. */
ext2_append_entry(block2, blksize,
- (struct ext2fs_direct_2 *)dest, entry);
+ (struct ext2fs_direct_2 *)dest, entry, csum_size);
/* Adjust length field of last entry of block 1. */
- last->e2d_reclen = block1 + blksize - (char *)last;
+ last->e2d_reclen = block1 + blksize - (char *)last - csum_size;
} else {
/* Add entry to block 1. */
- ext2_append_entry(block1, blksize, last, entry);
+ ext2_append_entry(block1, blksize, last, entry, csum_size);
/* Adjust length field of last entry of block 2. */
((struct ext2fs_direct_2 *)dest)->e2d_reclen =
- block2 + blksize - dest;
+ block2 + blksize - dest - csum_size;
}
+ if (csum_size) {
+ ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block1, blksize));
+ ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block2, blksize));
+ }
+
return (0);
}
@@ -680,13 +701,14 @@
hash_version = root->h_info.h_hash_version;
if (hash_version <= EXT2_HTREE_TEA)
hash_version += m_fs->e2fs_uhash;
- ext2_htree_split_dirblock(buf1, buf2, blksize, fs->e3fs_hash_seed,
+ ext2_htree_split_dirblock(dp, buf1, buf2, blksize, fs->e3fs_hash_seed,
hash_version, &split_hash, new_entry);
ext2_htree_insert_entry(&info, split_hash, 2);
/*
* Write directory block 0.
*/
+ ext2_dx_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
if (DOINGASYNC(vp)) {
bdwrite(bp);
error = 0;
@@ -700,6 +722,7 @@
/*
* Write directory block 1.
*/
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)buf1);
error = ext2_htree_append_block(vp, buf1, cnp, blksize);
if (error)
goto out1;
@@ -707,6 +730,7 @@
/*
* Write directory block 2.
*/
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)buf2);
error = ext2_htree_append_block(vp, buf2, cnp, blksize);
free(buf1, M_TEMP);
@@ -825,6 +849,8 @@
split_hash, blknum);
/* Write new index node to disk */
+ ext2_dx_csum_set(ip,
+ (struct ext2fs_direct_2 *)dst_bp->b_data);
error = bwrite(dst_bp);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (error)
@@ -863,7 +889,7 @@
/* Split target directory block */
newdirblock = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO);
- ext2_htree_split_dirblock((char *)bp->b_data, newdirblock, blksize,
+ ext2_htree_split_dirblock(ip, (char *)bp->b_data, newdirblock, blksize,
fs->e3fs_hash_seed, hash_version, &split_hash, entry);
cursize = roundup(ip->i_size, blksize);
dirsize = cursize + blksize;
@@ -873,11 +899,13 @@
ext2_htree_insert_entry(&info, split_hash, blknum);
/* Write the new directory block to the end of the directory */
+ ext2_dirent_csum_set(ip, (struct ext2fs_direct_2 *)newdirblock);
error = ext2_htree_append_block(dvp, newdirblock, cnp, blksize);
if (error)
goto finish;
/* Write the target directory block */
+ ext2_dirent_csum_set(ip, (struct ext2fs_direct_2 *)bp->b_data);
error = bwrite(bp);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (error)
@@ -885,7 +913,7 @@
write_bp = 1;
/* Write the index block */
- error = ext2_htree_writebuf(&info);
+ error = ext2_htree_writebuf(ip, &info);
if (!error)
write_info = 1;
Index: head/sys/fs/ext2fs/ext2_inode_cnv.c
===================================================================
--- head/sys/fs/ext2fs/ext2_inode_cnv.c
+++ head/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -136,6 +136,7 @@
memcpy(ip->i_data, ei->e2di_blocks, sizeof(ei->e2di_blocks));
+ /* Verify inode csum. */
return (ext2_ei_csum_verify(ip, ei));
}
@@ -197,7 +198,7 @@
memcpy(ei->e2di_blocks, ip->i_data, sizeof(ei->e2di_blocks));
- /* Set inode csum */
+ /* Set inode csum. */
ext2_ei_csum_set(ip, ei);
return (0);
Index: head/sys/fs/ext2fs/ext2_lookup.c
===================================================================
--- head/sys/fs/ext2fs/ext2_lookup.c
+++ head/sys/fs/ext2fs/ext2_lookup.c
@@ -930,7 +930,7 @@
memcpy(bp->b_data, &newdir, sizeof(struct ext2fs_direct_2));
- ext2_dir_blk_csum_set(dp, bp);
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
error = bwrite(bp);
if (error)
return (error);
@@ -1030,7 +1030,7 @@
ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
}
bcopy((caddr_t)entry, (caddr_t)ep, (u_int)newentrysize);
- ext2_dir_blk_csum_set(dp, bp);
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
if (DOINGASYNC(dvp)) {
bdwrite(bp);
error = 0;
@@ -1088,7 +1088,7 @@
else
rep = (struct ext2fs_direct_2 *)((char *)ep + ep->e2d_reclen);
ep->e2d_reclen += rep->e2d_reclen;
- ext2_dir_blk_csum_set(dp, bp);
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
if (DOINGASYNC(dvp) && dp->i_count != 0)
bdwrite(bp);
else
@@ -1119,7 +1119,7 @@
ep->e2d_type = DTTOFT(IFTODT(ip->i_mode));
else
ep->e2d_type = EXT2_FT_UNKNOWN;
- ext2_dir_blk_csum_set(dp, bp);
+ ext2_dirent_csum_set(dp, (struct ext2fs_direct_2 *)bp->b_data);
error = bwrite(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
Index: head/sys/fs/ext2fs/ext2_vnops.c
===================================================================
--- head/sys/fs/ext2fs/ext2_vnops.c
+++ head/sys/fs/ext2fs/ext2_vnops.c
@@ -1091,9 +1091,8 @@
"rename: mangled dir");
} else {
dirbuf->dotdot_ino = newparent;
- ext2_dir_blk_csum_set_mem(ip,
- (char *)dirbuf,
- ip->i_e2fs->e2fs_bsize);
+ ext2_dirent_csum_set(ip,
+ (struct ext2fs_direct_2 *)dirbuf);
(void)vn_rdwr(UIO_WRITE, fvp,
(caddr_t)dirbuf,
ip->i_e2fs->e2fs_bsize,
@@ -1284,14 +1283,6 @@
#endif /* UFS_ACL */
-static void
-ext2_init_dirent_tail(struct ext2fs_direct_tail *tp)
-{
- memset(tp, 0, sizeof(struct ext2fs_direct_tail));
- tp->e2dt_rec_len = sizeof(struct ext2fs_direct_tail);
- tp->e2dt_reserved_ft = EXT2_FT_DIR_CSUM;
-}
-
/*
* Mkdir system call
*/
@@ -1400,7 +1391,7 @@
ext2_init_dirent_tail(EXT2_DIRENT_TAIL(buf, DIRBLKSIZ));
}
memcpy(buf, &dirtemplate, sizeof(dirtemplate));
- ext2_dir_blk_csum_set_mem(ip, buf, DIRBLKSIZ);
+ ext2_dirent_csum_set(ip, (struct ext2fs_direct_2 *)buf);
error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)buf,
DIRBLKSIZ, (off_t)0, UIO_SYSSPACE,
IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jul 26, 3:36 PM (1 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35541712
Default Alt Text
D15396.diff (16 KB)
Attached To
Mode
D15396: Fix directory blocks checksumming.
Attached
Detach File
Event Timeline
Log In to Comment