Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_htree.c
Show First 20 Lines • Show All 505 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
ext2_append_entry(char *block, uint32_t blksize, | ext2_append_entry(char *block, uint32_t blksize, | ||||
struct ext2fs_direct_2 *last_entry, | struct ext2fs_direct_2 *last_entry, | ||||
struct ext2fs_direct_2 *new_entry, int csum_size) | struct ext2fs_direct_2 *new_entry, int csum_size) | ||||
{ | { | ||||
uint16_t entry_len; | uint16_t entry_len; | ||||
entry_len = EXT2_DIR_REC_LEN(last_entry->e2d_namlen); | entry_len = EXT2_DIR_REC_LEN(le16toh(last_entry->e2d_namlen)); | ||||
last_entry->e2d_reclen = entry_len; | last_entry->e2d_reclen = htole16(entry_len); | ||||
last_entry = (struct ext2fs_direct_2 *)((char *)last_entry + entry_len); | last_entry = (struct ext2fs_direct_2 *)((char *)last_entry + entry_len); | ||||
new_entry->e2d_reclen = block + blksize - (char *)last_entry - csum_size; | new_entry->e2d_reclen = htole16(block + blksize - (char *)last_entry - | ||||
memcpy(last_entry, new_entry, EXT2_DIR_REC_LEN(new_entry->e2d_namlen)); | csum_size); | ||||
memcpy(last_entry, new_entry, | |||||
EXT2_DIR_REC_LEN(le16toh(new_entry->e2d_namlen))); | |||||
} | } | ||||
/* | /* | ||||
* Move half of entries from the old directory block to the new one. | * Move half of entries from the old directory block to the new one. | ||||
*/ | */ | ||||
static int | static int | ||||
ext2_htree_split_dirblock(struct inode *ip, char *block1, char *block2, | ext2_htree_split_dirblock(struct inode *ip, char *block1, char *block2, | ||||
uint32_t blksize, uint32_t *hash_seed, uint8_t hash_version, | uint32_t blksize, uint32_t *hash_seed, uint8_t hash_version, | ||||
Show All 17 Lines | sort_info = (struct ext2fs_htree_sort_entry *) | ||||
((char *)block2 + blksize); | ((char *)block2 + blksize); | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) | ||||
csum_size = sizeof(struct ext2fs_direct_tail); | csum_size = sizeof(struct ext2fs_direct_tail); | ||||
/* | /* | ||||
* Calculate name hash value for the entry which is to be added. | * Calculate name hash value for the entry which is to be added. | ||||
*/ | */ | ||||
ext2_htree_hash(entry->e2d_name, entry->e2d_namlen, hash_seed, | ext2_htree_hash(entry->e2d_name, le16toh(entry->e2d_namlen), | ||||
hash_version, &entry_hash, NULL); | hash_seed, hash_version, &entry_hash, NULL); | ||||
/* | /* | ||||
* Fill in directory entry sort descriptors. | * Fill in directory entry sort descriptors. | ||||
*/ | */ | ||||
while ((char *)ep < block1 + blksize - csum_size) { | while ((char *)ep < block1 + blksize - csum_size) { | ||||
if (ep->e2d_ino && ep->e2d_namlen) { | if (ep->e2d_ino && ep->e2d_namlen) { | ||||
entry_cnt++; | entry_cnt++; | ||||
sort_info--; | sort_info--; | ||||
sort_info->h_size = ep->e2d_reclen; | sort_info->h_size = le16toh(ep->e2d_reclen); | ||||
sort_info->h_offset = (char *)ep - block1; | sort_info->h_offset = (char *)ep - block1; | ||||
ext2_htree_hash(ep->e2d_name, ep->e2d_namlen, | ext2_htree_hash(ep->e2d_name, le16toh(ep->e2d_namlen), | ||||
hash_seed, hash_version, | hash_seed, hash_version, | ||||
&sort_info->h_hash, NULL); | &sort_info->h_hash, NULL); | ||||
} | } | ||||
ep = (struct ext2fs_direct_2 *) | ep = (struct ext2fs_direct_2 *) | ||||
((char *)ep + ep->e2d_reclen); | ((char *)ep + le16toh(ep->e2d_reclen)); | ||||
} | } | ||||
/* | /* | ||||
* Sort directory entry descriptors by name hash value. | * Sort directory entry descriptors by name hash value. | ||||
*/ | */ | ||||
qsort(sort_info, entry_cnt, sizeof(struct ext2fs_htree_sort_entry), | qsort(sort_info, entry_cnt, sizeof(struct ext2fs_htree_sort_entry), | ||||
ext2_htree_cmp_sort_entry); | ext2_htree_cmp_sort_entry); | ||||
Show All 17 Lines | ext2_htree_split_dirblock(struct inode *ip, char *block1, char *block2, | ||||
/* | /* | ||||
* Move half of directory entries from block 1 to block 2. | * Move half of directory entries from block 1 to block 2. | ||||
*/ | */ | ||||
for (k = i + 1; k < entry_cnt; k++) { | for (k = i + 1; k < entry_cnt; k++) { | ||||
ep = (struct ext2fs_direct_2 *)((char *)block1 + | ep = (struct ext2fs_direct_2 *)((char *)block1 + | ||||
sort_info[k].h_offset); | sort_info[k].h_offset); | ||||
entry_len = EXT2_DIR_REC_LEN(ep->e2d_namlen); | entry_len = EXT2_DIR_REC_LEN(ep->e2d_namlen); | ||||
memcpy(dest, ep, entry_len); | memcpy(dest, ep, entry_len); | ||||
((struct ext2fs_direct_2 *)dest)->e2d_reclen = entry_len; | ((struct ext2fs_direct_2 *)dest)->e2d_reclen = | ||||
htole16(entry_len); | |||||
/* Mark directory entry as unused. */ | /* Mark directory entry as unused. */ | ||||
ep->e2d_ino = 0; | ep->e2d_ino = 0; | ||||
dest += entry_len; | dest += entry_len; | ||||
} | } | ||||
dest -= entry_len; | dest -= entry_len; | ||||
/* Shrink directory entries in block 1. */ | /* Shrink directory entries in block 1. */ | ||||
last = (struct ext2fs_direct_2 *)block1; | last = (struct ext2fs_direct_2 *)block1; | ||||
entry_len = 0; | entry_len = 0; | ||||
for (offset = 0; offset < blksize - csum_size; ) { | for (offset = 0; offset < blksize - csum_size; ) { | ||||
ep = (struct ext2fs_direct_2 *)(block1 + offset); | ep = (struct ext2fs_direct_2 *)(block1 + offset); | ||||
offset += ep->e2d_reclen; | offset += le16toh(ep->e2d_reclen); | ||||
if (ep->e2d_ino) { | if (ep->e2d_ino) { | ||||
last = (struct ext2fs_direct_2 *) | last = (struct ext2fs_direct_2 *) | ||||
((char *)last + entry_len); | ((char *)last + entry_len); | ||||
entry_len = EXT2_DIR_REC_LEN(ep->e2d_namlen); | entry_len = EXT2_DIR_REC_LEN(le16toh(ep->e2d_namlen)); | ||||
memcpy((void *)last, (void *)ep, entry_len); | memcpy((void *)last, (void *)ep, entry_len); | ||||
last->e2d_reclen = entry_len; | last->e2d_reclen = htole16(entry_len); | ||||
} | } | ||||
} | } | ||||
if (entry_hash >= *split_hash) { | if (entry_hash >= *split_hash) { | ||||
/* Add entry to block 2. */ | /* Add entry to block 2. */ | ||||
ext2_append_entry(block2, blksize, | ext2_append_entry(block2, blksize, | ||||
(struct ext2fs_direct_2 *)dest, entry, csum_size); | (struct ext2fs_direct_2 *)dest, entry, csum_size); | ||||
/* Adjust length field of last entry of block 1. */ | /* Adjust length field of last entry of block 1. */ | ||||
last->e2d_reclen = block1 + blksize - (char *)last - csum_size; | last->e2d_reclen = htole16(block1 + blksize - (char *)last - csum_size); | ||||
} else { | } else { | ||||
/* Add entry to block 1. */ | /* Add entry to block 1. */ | ||||
ext2_append_entry(block1, blksize, last, entry, csum_size); | ext2_append_entry(block1, blksize, last, entry, csum_size); | ||||
/* Adjust length field of last entry of block 2. */ | /* Adjust length field of last entry of block 2. */ | ||||
((struct ext2fs_direct_2 *)dest)->e2d_reclen = | ((struct ext2fs_direct_2 *)dest)->e2d_reclen = | ||||
block2 + blksize - dest - csum_size; | htole16(block2 + blksize - dest - csum_size); | ||||
} | } | ||||
if (csum_size) { | if (csum_size) { | ||||
ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block1, blksize)); | ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block1, blksize)); | ||||
ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block2, blksize)); | ext2_init_dirent_tail(EXT2_DIRENT_TAIL(block2, blksize)); | ||||
} | } | ||||
return (0); | return (0); | ||||
Show All 27 Lines | ext2_htree_create_index(struct vnode *vp, struct componentname *cnp, | ||||
buf1 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | buf1 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | ||||
buf2 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | buf2 = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | ||||
if ((error = ext2_blkatoff(vp, 0, NULL, &bp)) != 0) | if ((error = ext2_blkatoff(vp, 0, NULL, &bp)) != 0) | ||||
goto out; | goto out; | ||||
root = (struct ext2fs_htree_root *)bp->b_data; | root = (struct ext2fs_htree_root *)bp->b_data; | ||||
dotdot = (struct ext2fs_direct_2 *)((char *)&(root->h_dotdot)); | dotdot = (struct ext2fs_direct_2 *)((char *)&(root->h_dotdot)); | ||||
ep = (struct ext2fs_direct_2 *)((char *)dotdot + dotdot->e2d_reclen); | ep = (struct ext2fs_direct_2 *)((char *)dotdot + | ||||
le16toh(dotdot->e2d_reclen)); | |||||
dirlen = (char *)root + blksize - (char *)ep; | dirlen = (char *)root + blksize - (char *)ep; | ||||
memcpy(buf1, ep, dirlen); | memcpy(buf1, ep, dirlen); | ||||
ep = (struct ext2fs_direct_2 *)buf1; | ep = (struct ext2fs_direct_2 *)buf1; | ||||
while ((char *)ep < buf1 + dirlen) | while ((char *)ep < buf1 + dirlen) | ||||
ep = (struct ext2fs_direct_2 *) | ep = (struct ext2fs_direct_2 *) | ||||
((char *)ep + ep->e2d_reclen); | ((char *)ep + le16toh(ep->e2d_reclen)); | ||||
ep->e2d_reclen = buf1 + blksize - (char *)ep; | ep->e2d_reclen = htole16(buf1 + blksize - (char *)ep); | ||||
dp->i_flag |= IN_E3INDEX; | dp->i_flag |= IN_E3INDEX; | ||||
/* | /* | ||||
* Initialize index root. | * Initialize index root. | ||||
*/ | */ | ||||
dotdot->e2d_reclen = blksize - EXT2_DIR_REC_LEN(1); | dotdot->e2d_reclen = blksize - EXT2_DIR_REC_LEN(1); | ||||
memset(&root->h_info, 0, sizeof(root->h_info)); | memset(&root->h_info, 0, sizeof(root->h_info)); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | ext2_htree_add_entry(struct vnode *dvp, struct ext2fs_direct_2 *entry, | ||||
ent_num = ext2_htree_get_count(entries); | ent_num = ext2_htree_get_count(entries); | ||||
if (ent_num == ext2_htree_get_limit(entries)) { | if (ent_num == ext2_htree_get_limit(entries)) { | ||||
/* Split the index node. */ | /* Split the index node. */ | ||||
root_entires = info.h_levels[0].h_entries; | root_entires = info.h_levels[0].h_entries; | ||||
newidxblock = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | newidxblock = malloc(blksize, M_TEMP, M_WAITOK | M_ZERO); | ||||
dst_node = (struct ext2fs_htree_node *)newidxblock; | dst_node = (struct ext2fs_htree_node *)newidxblock; | ||||
memset(&dst_node->h_fake_dirent, 0, | memset(&dst_node->h_fake_dirent, 0, | ||||
sizeof(dst_node->h_fake_dirent)); | sizeof(dst_node->h_fake_dirent)); | ||||
dst_node->h_fake_dirent.e2d_reclen = blksize; | dst_node->h_fake_dirent.e2d_reclen = htole32(blksize); | ||||
cursize = roundup(ip->i_size, blksize); | cursize = roundup(ip->i_size, blksize); | ||||
dirsize = cursize + blksize; | dirsize = cursize + blksize; | ||||
blknum = dirsize / blksize - 1; | blknum = dirsize / blksize - 1; | ||||
ext2_dx_csum_set(ip, (struct ext2fs_direct_2 *)newidxblock); | ext2_dx_csum_set(ip, (struct ext2fs_direct_2 *)newidxblock); | ||||
error = ext2_htree_append_block(dvp, newidxblock, | error = ext2_htree_append_block(dvp, newidxblock, | ||||
cnp, blksize); | cnp, blksize); | ||||
if (error) | if (error) | ||||
▲ Show 20 Lines • Show All 127 Lines • Show Last 20 Lines |