Fri Jun 24 17:21:30 2016 UTC ()
GSoC 2016 (Hrishikesh Goyal): Htree index support from FreeBSD


(christos)
diff -r1.37 -r1.38 src/sys/ufs/ext2fs/ext2fs.h
diff -r1.19 -r1.20 src/sys/ufs/ext2fs/ext2fs_dir.h
diff -r1.48 -r1.49 src/sys/ufs/ext2fs/ext2fs_extern.h
diff -r0 -r1.1 src/sys/ufs/ext2fs/ext2fs_hash.c
diff -r0 -r1.1 src/sys/ufs/ext2fs/ext2fs_hash.h
diff -r0 -r1.1 src/sys/ufs/ext2fs/ext2fs_htree.c
diff -r0 -r1.1 src/sys/ufs/ext2fs/ext2fs_htree.h
diff -r1.79 -r1.80 src/sys/ufs/ext2fs/ext2fs_lookup.c

cvs diff -r1.37 -r1.38 src/sys/ufs/ext2fs/ext2fs.h (expand / switch to unified diff)

--- src/sys/ufs/ext2fs/ext2fs.h 2016/06/03 15:35:48 1.37
+++ src/sys/ufs/ext2fs/ext2fs.h 2016/06/24 17:21:30 1.38
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ext2fs.h,v 1.37 2016/06/03 15:35:48 christos Exp $ */ 1/* $NetBSD: ext2fs.h,v 1.38 2016/06/24 17:21:30 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1993 4 * Copyright (c) 1982, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -225,26 +225,27 @@ struct ext2fs { @@ -225,26 +225,27 @@ struct ext2fs {
225 uint32_t e4fs_proj_quota_inum; /* inode for tracking project quota */ 225 uint32_t e4fs_proj_quota_inum; /* inode for tracking project quota */
226 uint32_t e4fs_chksum_seed; /* checksum seed */ 226 uint32_t e4fs_chksum_seed; /* checksum seed */
227 uint32_t e4fs_reserved[98]; /* padding to the end of the block */ 227 uint32_t e4fs_reserved[98]; /* padding to the end of the block */
228 uint32_t e4fs_sbchksum; /* superblock checksum */ 228 uint32_t e4fs_sbchksum; /* superblock checksum */
229}; 229};
230 230
231 231
232/* in-memory data for ext2fs */ 232/* in-memory data for ext2fs */
233struct m_ext2fs { 233struct m_ext2fs {
234 struct ext2fs e2fs; 234 struct ext2fs e2fs;
235 u_char e2fs_fsmnt[MAXMNTLEN]; /* name mounted on */ 235 u_char e2fs_fsmnt[MAXMNTLEN]; /* name mounted on */
236 int8_t e2fs_ronly; /* mounted read-only flag */ 236 int8_t e2fs_ronly; /* mounted read-only flag */
237 int8_t e2fs_fmod; /* super block modified flag */ 237 int8_t e2fs_fmod; /* super block modified flag */
 238 int8_t e2fs_uhash; /* 3 if hash should be signed, 0 if not */
238 int32_t e2fs_bsize; /* block size */ 239 int32_t e2fs_bsize; /* block size */
239 int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */ 240 int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */
240 int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */ 241 int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */
241 int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */ 242 int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */
242 int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ 243 int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
243 int32_t e2fs_ncg; /* number of cylinder groups */ 244 int32_t e2fs_ncg; /* number of cylinder groups */
244 int32_t e2fs_ngdb; /* number of group descriptor block */ 245 int32_t e2fs_ngdb; /* number of group descriptor block */
245 int32_t e2fs_ipb; /* number of inodes per block */ 246 int32_t e2fs_ipb; /* number of inodes per block */
246 int32_t e2fs_itpg; /* number of inode table per group */ 247 int32_t e2fs_itpg; /* number of inode table per group */
247 struct ext2_gd *e2fs_gd; /* group descripors */ 248 struct ext2_gd *e2fs_gd; /* group descripors */
248}; 249};
249 250
250 251
@@ -321,26 +322,32 @@ struct m_ext2fs { @@ -321,26 +322,32 @@ struct m_ext2fs {
321 * upper 32bit of size for >2GB files 322 * upper 32bit of size for >2GB files
322 * - EXT2F_INCOMPAT_FTYPE 323 * - EXT2F_INCOMPAT_FTYPE
323 * store file type to e2d_type in struct ext2fs_direct 324 * store file type to e2d_type in struct ext2fs_direct
324 * (on REV0 e2d_namlen is uint16_t and no e2d_type, like ffs) 325 * (on REV0 e2d_namlen is uint16_t and no e2d_type, like ffs)
325 */ 326 */
326#define EXT2F_COMPAT_SUPP 0x0000 327#define EXT2F_COMPAT_SUPP 0x0000
327#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \ 328#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \
328 | EXT2F_ROCOMPAT_LARGEFILE \ 329 | EXT2F_ROCOMPAT_LARGEFILE \
329 | EXT2F_ROCOMPAT_HUGE_FILE) 330 | EXT2F_ROCOMPAT_HUGE_FILE)
330#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE \ 331#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE \
331 | EXT2F_INCOMPAT_EXTENTS) 332 | EXT2F_INCOMPAT_EXTENTS)
332 333
333/* 334/*
 335 * Feature set definitions
 336 */
 337#define EXT2_HAS_COMPAT_FEATURE(sb, mask) \
 338 ((sb)->e2fs.e2fs_features_compat & htole32(mask))
 339
 340/*
334 * Definitions of behavior on errors 341 * Definitions of behavior on errors
335 */ 342 */
336#define E2FS_BEH_CONTINUE 1 /* continue operation */ 343#define E2FS_BEH_CONTINUE 1 /* continue operation */
337#define E2FS_BEH_READONLY 2 /* remount fs read only */ 344#define E2FS_BEH_READONLY 2 /* remount fs read only */
338#define E2FS_BEH_PANIC 3 /* cause panic */ 345#define E2FS_BEH_PANIC 3 /* cause panic */
339#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE 346#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE
340 347
341/* 348/*
342 * OS identification 349 * OS identification
343 */ 350 */
344#define E2FS_OS_LINUX 0 351#define E2FS_OS_LINUX 0
345#define E2FS_OS_HURD 1 352#define E2FS_OS_HURD 1
346#define E2FS_OS_MASIX 2 353#define E2FS_OS_MASIX 2

cvs diff -r1.19 -r1.20 src/sys/ufs/ext2fs/ext2fs_dir.h (expand / switch to unified diff)

--- src/sys/ufs/ext2fs/ext2fs_dir.h 2012/05/09 00:21:18 1.19
+++ src/sys/ufs/ext2fs/ext2fs_dir.h 2016/06/24 17:21:30 1.20
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ext2fs_dir.h,v 1.19 2012/05/09 00:21:18 riastradh Exp $ */ 1/* $NetBSD: ext2fs_dir.h,v 1.20 2016/06/24 17:21:30 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1993 4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -104,26 +104,40 @@ @@ -104,26 +104,40 @@
104 * It's safe to use this for rev 0 as well because all ext2 are little-endian. 104 * It's safe to use this for rev 0 as well because all ext2 are little-endian.
105 */ 105 */
106 106
107#define EXT2FS_MAXNAMLEN 255 107#define EXT2FS_MAXNAMLEN 255
108 108
109struct ext2fs_direct { 109struct ext2fs_direct {
110 uint32_t e2d_ino; /* inode number of entry */ 110 uint32_t e2d_ino; /* inode number of entry */
111 uint16_t e2d_reclen; /* length of this record */ 111 uint16_t e2d_reclen; /* length of this record */
112 uint8_t e2d_namlen; /* length of string in d_name */ 112 uint8_t e2d_namlen; /* length of string in d_name */
113 uint8_t e2d_type; /* file type */ 113 uint8_t e2d_type; /* file type */
114 char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */ 114 char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
115}; 115};
116 116
 117enum ext2fs_slotstatus {
 118 NONE,
 119 COMPACT,
 120 FOUND
 121};
 122
 123struct ext2fs_searchslot {
 124 enum ext2fs_slotstatus slotstatus;
 125 doff_t slotoffset; /* offset of area with free space */
 126 int slotsize; /* size of area at slotoffset */
 127 int slotfreespace; /* amount of space free in slot */
 128 int slotneeded; /* sizeof the entry we are seeking */
 129};
 130
117/* Ext2 directory file types (not the same as FFS. Sigh.) */ 131/* Ext2 directory file types (not the same as FFS. Sigh.) */
118#define EXT2_FT_UNKNOWN 0 132#define EXT2_FT_UNKNOWN 0
119#define EXT2_FT_REG_FILE 1 133#define EXT2_FT_REG_FILE 1
120#define EXT2_FT_DIR 2 134#define EXT2_FT_DIR 2
121#define EXT2_FT_CHRDEV 3 135#define EXT2_FT_CHRDEV 3
122#define EXT2_FT_BLKDEV 4 136#define EXT2_FT_BLKDEV 4
123#define EXT2_FT_FIFO 5 137#define EXT2_FT_FIFO 5
124#define EXT2_FT_SOCK 6 138#define EXT2_FT_SOCK 6
125#define EXT2_FT_SYMLINK 7 139#define EXT2_FT_SYMLINK 7
126 140
127#define EXT2_FT_MAX 8 141#define EXT2_FT_MAX 8
128 142
129#define E2IFTODT(mode) (((mode) & 0170000) >> 12) 143#define E2IFTODT(mode) (((mode) & 0170000) >> 12)
@@ -169,14 +183,24 @@ inot2ext2dt(uint16_t type) @@ -169,14 +183,24 @@ inot2ext2dt(uint16_t type)
169struct ext2fs_dirtemplate { 183struct ext2fs_dirtemplate {
170 uint32_t dot_ino; 184 uint32_t dot_ino;
171 int16_t dot_reclen; 185 int16_t dot_reclen;
172 uint8_t dot_namlen; 186 uint8_t dot_namlen;
173 uint8_t dot_type; 187 uint8_t dot_type;
174 char dot_name[4]; /* must be multiple of 4 */ 188 char dot_name[4]; /* must be multiple of 4 */
175 uint32_t dotdot_ino; 189 uint32_t dotdot_ino;
176 int16_t dotdot_reclen; 190 int16_t dotdot_reclen;
177 uint8_t dotdot_namlen; 191 uint8_t dotdot_namlen;
178 uint8_t dotdot_type; 192 uint8_t dotdot_type;
179 char dotdot_name[4]; /* ditto */ 193 char dotdot_name[4]; /* ditto */
180}; 194};
181 195
 196/*
 197 * EXT2_DIR_PAD defines the directory entries boundaries
 198 *
 199 * NOTE: It must be a multiple of 4
 200 */
 201#define EXT2_DIR_PAD 4
 202#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
 203#define EXT2_DIR_REC_LEN(namelen) \
 204 (((namelen) + 8 + EXT2_DIR_ROUND) & ~EXT2_DIR_ROUND)
 205
182#endif /* !_UFS_EXT2FS_EXT2FS_DIR_H_ */ 206#endif /* !_UFS_EXT2FS_EXT2FS_DIR_H_ */

cvs diff -r1.48 -r1.49 src/sys/ufs/ext2fs/ext2fs_extern.h (expand / switch to unified diff)

--- src/sys/ufs/ext2fs/ext2fs_extern.h 2015/03/27 17:27:56 1.48
+++ src/sys/ufs/ext2fs/ext2fs_extern.h 2016/06/24 17:21:30 1.49
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ext2fs_extern.h,v 1.48 2015/03/27 17:27:56 riastradh Exp $ */ 1/* $NetBSD: ext2fs_extern.h,v 1.49 2016/06/24 17:21:30 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993, 1994 4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -68,26 +68,27 @@ struct m_ext2fs; @@ -68,26 +68,27 @@ struct m_ext2fs;
68struct inode; 68struct inode;
69struct mount; 69struct mount;
70struct nameidata; 70struct nameidata;
71struct lwp; 71struct lwp;
72struct proc; 72struct proc;
73struct statvfs; 73struct statvfs;
74struct timeval; 74struct timeval;
75struct ufsmount; 75struct ufsmount;
76struct uio; 76struct uio;
77struct vnode; 77struct vnode;
78struct mbuf; 78struct mbuf;
79struct componentname; 79struct componentname;
80struct ufs_lookup_results; 80struct ufs_lookup_results;
 81struct ext2fs_searchslot;
81 82
82extern struct pool ext2fs_inode_pool; /* memory pool for inodes */ 83extern struct pool ext2fs_inode_pool; /* memory pool for inodes */
83extern struct pool ext2fs_dinode_pool; /* memory pool for dinodes */ 84extern struct pool ext2fs_dinode_pool; /* memory pool for dinodes */
84 85
85#define EXT2FS_ITIMES(ip, acc, mod, cre) \ 86#define EXT2FS_ITIMES(ip, acc, mod, cre) \
86 while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \ 87 while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
87 ext2fs_itimes(ip, acc, mod, cre) 88 ext2fs_itimes(ip, acc, mod, cre)
88 89
89__BEGIN_DECLS 90__BEGIN_DECLS
90 91
91/* ext2fs_alloc.c */ 92/* ext2fs_alloc.c */
92int ext2fs_alloc(struct inode *, daddr_t, daddr_t , kauth_cred_t, 93int ext2fs_alloc(struct inode *, daddr_t, daddr_t , kauth_cred_t,
93 daddr_t *); 94 daddr_t *);
@@ -110,26 +111,29 @@ int ext2fs_bmap(void *); @@ -110,26 +111,29 @@ int ext2fs_bmap(void *);
110/* ext2fs_inode.c */ 111/* ext2fs_inode.c */
111uint64_t ext2fs_size(struct inode *); 112uint64_t ext2fs_size(struct inode *);
112int ext2fs_setsize(struct inode *, uint64_t); 113int ext2fs_setsize(struct inode *, uint64_t);
113uint64_t ext2fs_nblock(struct inode *); 114uint64_t ext2fs_nblock(struct inode *);
114int ext2fs_setnblock(struct inode *, uint64_t); 115int ext2fs_setnblock(struct inode *, uint64_t);
115int ext2fs_update(struct vnode *, const struct timespec *, 116int ext2fs_update(struct vnode *, const struct timespec *,
116 const struct timespec *, int); 117 const struct timespec *, int);
117int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t); 118int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t);
118int ext2fs_inactive(void *); 119int ext2fs_inactive(void *);
119 120
120/* ext2fs_lookup.c */ 121/* ext2fs_lookup.c */
121int ext2fs_readdir(void *); 122int ext2fs_readdir(void *);
122int ext2fs_lookup(void *); 123int ext2fs_lookup(void *);
 124int ext2fs_search_dirblock(struct inode *, void *, int *,
 125 const char *, int , int *, doff_t *, doff_t *, doff_t *,
 126 struct ext2fs_searchslot *);
123int ext2fs_direnter(struct inode *, struct vnode *, 127int ext2fs_direnter(struct inode *, struct vnode *,
124 const struct ufs_lookup_results *, 128 const struct ufs_lookup_results *,
125 struct componentname *); 129 struct componentname *);
126int ext2fs_dirremove(struct vnode *, const struct ufs_lookup_results *, 130int ext2fs_dirremove(struct vnode *, const struct ufs_lookup_results *,
127 struct componentname *); 131 struct componentname *);
128int ext2fs_dirrewrite(struct inode *, const struct ufs_lookup_results *, 132int ext2fs_dirrewrite(struct inode *, const struct ufs_lookup_results *,
129 struct inode *, struct componentname *); 133 struct inode *, struct componentname *);
130int ext2fs_dirempty(struct inode *, ino_t, kauth_cred_t); 134int ext2fs_dirempty(struct inode *, ino_t, kauth_cred_t);
131 135
132/* ext2fs_subr.c */ 136/* ext2fs_subr.c */
133int ext2fs_blkatoff(struct vnode *, off_t, char **, struct buf **); 137int ext2fs_blkatoff(struct vnode *, off_t, char **, struct buf **);
134void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int); 138void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int);
135void ext2fs_itimes(struct inode *, const struct timespec *, 139void ext2fs_itimes(struct inode *, const struct timespec *,
@@ -162,22 +166,31 @@ int ext2fs_link(void *); @@ -162,22 +166,31 @@ int ext2fs_link(void *);
162int ext2fs_rename(void *); 166int ext2fs_rename(void *);
163int ext2fs_mkdir(void *); 167int ext2fs_mkdir(void *);
164int ext2fs_rmdir(void *); 168int ext2fs_rmdir(void *);
165int ext2fs_symlink(void *); 169int ext2fs_symlink(void *);
166int ext2fs_readlink(void *); 170int ext2fs_readlink(void *);
167int ext2fs_advlock(void *); 171int ext2fs_advlock(void *);
168int ext2fs_fsync(void *); 172int ext2fs_fsync(void *);
169int ext2fs_vinit(struct mount *, int (**specops)(void *), 173int ext2fs_vinit(struct mount *, int (**specops)(void *),
170 int (**fifoops)(void *), struct vnode **); 174 int (**fifoops)(void *), struct vnode **);
171int ext2fs_makeinode(int, struct vnode *, struct vnode **, 175int ext2fs_makeinode(int, struct vnode *, struct vnode **,
172 struct componentname *cnp); 176 struct componentname *cnp);
173int ext2fs_reclaim(void *); 177int ext2fs_reclaim(void *);
174 178
 179/* ext2fs_hash.c */
 180int ext2fs_htree_hash(const char *, int, uint32_t *, int, uint32_t *,
 181 uint32_t *);
 182
 183/* ext2fs_htree.c */
 184int ext2fs_htree_has_idx(struct inode *);
 185int ext2fs_htree_lookup(struct inode *, const char *, int, struct buf **,
 186 int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
 187
175__END_DECLS 188__END_DECLS
176 189
177#define IS_EXT2_VNODE(vp) (vp->v_tag == VT_EXT2FS) 190#define IS_EXT2_VNODE(vp) (vp->v_tag == VT_EXT2FS)
178 191
179extern int (**ext2fs_vnodeop_p)(void *); 192extern int (**ext2fs_vnodeop_p)(void *);
180extern int (**ext2fs_specop_p)(void *); 193extern int (**ext2fs_specop_p)(void *);
181extern int (**ext2fs_fifoop_p)(void *); 194extern int (**ext2fs_fifoop_p)(void *);
182 195
183#endif /* !_UFS_EXT2FS_EXT2FS_EXTERN_H_ */ 196#endif /* !_UFS_EXT2FS_EXT2FS_EXTERN_H_ */

File Added: src/sys/ufs/ext2fs/ext2fs_hash.c
/*	$NetBSD: ext2fs_hash.c,v 1.1 2016/06/24 17:21:30 christos Exp $	*/

/*-
 * Copyright (c) 2010, 2013 Zheng Liu <lz@freebsd.org>
 * Copyright (c) 2012, Vyacheslav Matyushin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: head/sys/fs/ext2fs/ext2_hash.c 294504 2016-01-21 14:50:28Z pfg $
 */

/*
 * The following notice applies to the code in ext2_half_md4():
 *
 * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
 *
 * License to copy and use this software is granted provided that it
 * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
 * Algorithm" in all material mentioning or referencing this software
 * or this function.
 *
 * License is also granted to make and use derivative works provided
 * that such works are identified as "derived from the RSA Data
 * Security, Inc. MD4 Message-Digest Algorithm" in all material
 * mentioning or referencing the derived work.
 *
 * RSA Data Security, Inc. makes no representations concerning either
 * the merchantability of this software or the suitability of this
 * software for any particular purpose. It is provided "as is"
 * without express or implied warranty of any kind.
 *
 * These notices must be retained in any copies of any part of this
 * documentation and/or software.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_hash.c,v 1.1 2016/06/24 17:21:30 christos Exp $");

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <sys/mount.h>

#include <ufs/ext2fs/ext2fs_htree.h>
#include <ufs/ext2fs/ext2fs_hash.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ext2fs/ext2fs_extern.h>

/*
 * FF, GG, and HH are transformations for rounds 1, 2, and 3.
 * Rotation is separated from addition to prevent recomputation.
 */
#define FF(a, b, c, d, x, s) { \
	(a) += F ((b), (c), (d)) + (x); \
	(a) = ROTATE_LEFT ((a), (s)); \
}

#define GG(a, b, c, d, x, s) { \
	(a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \
	(a) = ROTATE_LEFT ((a), (s)); \
}

#define HH(a, b, c, d, x, s) { \
	(a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \
	(a) = ROTATE_LEFT ((a), (s)); \
}

static void
ext2fs_prep_hashbuf(const char *src, int slen, uint32_t *dst, int dlen,
    int unsigned_char)
{
	uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24);
	uint32_t buf_val;
	const unsigned char *ubuf = (const unsigned char *)src;
	const signed char *sbuf = (const signed char *)src;
	int len, i;
	int buf_byte;

	if (slen > dlen)
		len = dlen;
	else
		len = slen;

	buf_val = padding;

	for (i = 0; i < len; i++) {
		if (unsigned_char)
			buf_byte = (u_int)ubuf[i];
		else
			buf_byte = (int)sbuf[i];

		if ((i % 4) == 0)
			buf_val = padding;

		buf_val <<= 8;
		buf_val += buf_byte;

		if ((i % 4) == 3) {
			*dst++ = buf_val;
			dlen -= sizeof(uint32_t);
			buf_val = padding;
		}
	}

	dlen -= sizeof(uint32_t);
	if (dlen >= 0)
		*dst++ = buf_val;

	dlen -= sizeof(uint32_t);
	while (dlen >= 0) {
		*dst++ = padding;
		dlen -= sizeof(uint32_t);
	}
}

static uint32_t
ext2fs_legacy_hash(const char *name, int len, int unsigned_char)
{
	uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9;
	uint32_t multi = 0x6D22F5;
	const unsigned char *uname = (const unsigned char *)name;
	const signed char *sname = (const signed char *)name;
	int val, i;

	for (i = 0; i < len; i++) {
		if (unsigned_char)
			val = (u_int)*uname++;
		else
			val = (int)*sname++;

		h0 = h2 + (h1 ^ (val * multi));
		if (h0 & 0x80000000)
			h0 -= 0x7FFFFFFF;
		h2 = h1;
		h1 = h0;
	}

	return h1 << 1;
}

/*
 * MD4 basic transformation.  It transforms state based on block.
 *
 * This is a half md4 algorithm since Linux uses this algorithm for dir
 * index.  This function is derived from the RSA Data Security, Inc. MD4
 * Message-Digest Algorithm and was modified as necessary.
 *
 * The return value of this function is uint32_t in Linux, but actually we don't
 * need to check this value, so in our version this function doesn't return any
 * value.
 */
static void
ext2fs_half_md4(uint32_t hash[4], uint32_t data[8])
{
	uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3];

	/* Round 1 */
	FF(a, b, c, d, data[0],  3);
	FF(d, a, b, c, data[1],  7);
	FF(c, d, a, b, data[2], 11);
	FF(b, c, d, a, data[3], 19);
	FF(a, b, c, d, data[4],  3);
	FF(d, a, b, c, data[5],  7);
	FF(c, d, a, b, data[6], 11);
	FF(b, c, d, a, data[7], 19);

	/* Round 2 */
	GG(a, b, c, d, data[1],  3);
	GG(d, a, b, c, data[3],  5);
	GG(c, d, a, b, data[5],  9);
	GG(b, c, d, a, data[7], 13);
	GG(a, b, c, d, data[0],  3);
	GG(d, a, b, c, data[2],  5);
	GG(c, d, a, b, data[4],  9);
	GG(b, c, d, a, data[6], 13);

	/* Round 3 */
	HH(a, b, c, d, data[3],  3);
	HH(d, a, b, c, data[7],  9);
	HH(c, d, a, b, data[2], 11);
	HH(b, c, d, a, data[6], 15);
	HH(a, b, c, d, data[1],  3);
	HH(d, a, b, c, data[5],  9);
	HH(c, d, a, b, data[0], 11);
	HH(b, c, d, a, data[4], 15);

	hash[0] += a;
	hash[1] += b;
	hash[2] += c;
	hash[3] += d;
}

/*
 * Tiny Encryption Algorithm.
 */
static void
ext2fs_tea(uint32_t hash[4], uint32_t data[8])
{
	uint32_t tea_delta = 0x9E3779B9;
	uint32_t sum;
	uint32_t x = hash[0], y = hash[1];
	int n = 16;
	int i = 1;

	while (n-- > 0) {
		sum = i * tea_delta;
		x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]);
		y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]);
		i++;
	}

	hash[0] += x;
	hash[1] += y;
}

int
ext2fs_htree_hash(const char *name, int len,
    uint32_t *hash_seed, int hash_version,
    uint32_t *hash_major, uint32_t *hash_minor)
{
	uint32_t hash[4];
	uint32_t data[8];
	uint32_t major = 0, minor = 0;
	int unsigned_char = 0;

	if (!name || !hash_major)
		return (-1);

	if (len < 1 || len > 255)
		goto error;

	hash[0] = 0x67452301;
	hash[1] = 0xEFCDAB89;
	hash[2] = 0x98BADCFE;
	hash[3] = 0x10325476;

	if (hash_seed)
		memcpy(hash, hash_seed, sizeof(hash));

	switch (hash_version) {
	case EXT2_HTREE_TEA_UNSIGNED:
		unsigned_char = 1;
		/* FALLTHROUGH */
	case EXT2_HTREE_TEA:
		while (len > 0) {
			ext2fs_prep_hashbuf(name, len, data, 16, unsigned_char);
			ext2fs_tea(hash, data);
			len -= 16;
			name += 16;
		}
		major = hash[0];
		minor = hash[1];
		break;
	case EXT2_HTREE_LEGACY_UNSIGNED:
		unsigned_char = 1;
		/* FALLTHROUGH */
	case EXT2_HTREE_LEGACY:
		major = ext2fs_legacy_hash(name, len, unsigned_char);
		break;
	case EXT2_HTREE_HALF_MD4_UNSIGNED:
		unsigned_char = 1;
		/* FALLTHROUGH */
	case EXT2_HTREE_HALF_MD4:
		while (len > 0) {
			ext2fs_prep_hashbuf(name, len, data, 32, unsigned_char);
			ext2fs_half_md4(hash, data);
			len -= 32;
			name += 32;
		}
		major = hash[1];
		minor = hash[2];
		break;
	default:
		goto error;
	}

	major &= ~1;
	if (major == (EXT2_HTREE_EOF << 1))
		major = (EXT2_HTREE_EOF - 1) << 1;
	*hash_major = major;
	if (hash_minor)
		*hash_minor = minor;

	return 0;

error:
	*hash_major = 0;
	if (hash_minor)
		*hash_minor = 0;
	return -1;
}

File Added: src/sys/ufs/ext2fs/ext2fs_hash.h
/*	$NetBSD: ext2fs_hash.h,v 1.1 2016/06/24 17:21:30 christos Exp $	*/

/*-
 * Copyright (c) 2016 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef _EXT2FS_HASH_H_
#define _EXT2FS_HASH_H_

/* F, G, and H are MD4 functions */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))

/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))

#endif /* _EXT2FS_HASH_H_ */

File Added: src/sys/ufs/ext2fs/ext2fs_htree.c
/*	$NetBSD: ext2fs_htree.c,v 1.1 2016/06/24 17:21:30 christos Exp $	*/

/*-
 * Copyright (c) 2010, 2012 Zheng Liu <lz@freebsd.org>
 * Copyright (c) 2012, Vyacheslav Matyushin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: head/sys/fs/ext2fs/ext2_htree.c 294653 2016-01-24 02:41:49Z pfg $
 */
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_htree.c,v 1.1 2016/06/24 17:21:30 christos Exp $");

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
#include <sys/kernel.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/lockf.h>
#include <sys/pool.h>
#include <sys/signalvar.h>
#include <sys/kauth.h>

#include <ufs/ufs/dir.h>

#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ext2fs/ext2fs.h>

#include <ufs/ext2fs/ext2fs_extern.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs_htree.h>
#include <ufs/ext2fs/ext2fs_hash.h>

int
ext2fs_htree_has_idx(struct inode *ip)
{
	return EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX)
	    && (ip->i_din.e2fs_din->e2di_flags & EXT2_INDEX);
}

static off_t
ext2fs_htree_get_block(struct ext2fs_htree_entry *ep)
{
	return ep->h_blk & 0x00FFFFFF;
}


static void
ext2fs_htree_release(struct ext2fs_htree_lookup_info *info)
{
	for (u_int i = 0; i < info->h_levels_num; i++) {
		struct buf *bp = info->h_levels[i].h_bp;
		if (bp != NULL)
			brelse(bp, 0);
	}
}

static uint16_t
ext2fs_htree_get_limit(struct ext2fs_htree_entry *ep)
{
	return ((struct ext2fs_htree_count *)(ep))->h_entries_max;
}

static uint32_t
ext2fs_htree_root_limit(struct inode *ip, int len)
{
	uint32_t space = ip->i_e2fs->e2fs_bsize - EXT2_DIR_REC_LEN(1) -
	    EXT2_DIR_REC_LEN(2) - len;
	return space / sizeof(struct ext2fs_htree_entry);
}

static uint16_t
ext2fs_htree_get_count(struct ext2fs_htree_entry *ep)
{
	return ((struct ext2fs_htree_count *)(ep))->h_entries_num;
}

static uint32_t
ext2fs_htree_get_hash(struct ext2fs_htree_entry *ep)
{
	return ep->h_hash;
}

static int
ext2fs_htree_check_next(struct inode *ip, uint32_t hash, const char *name,
    struct ext2fs_htree_lookup_info *info)
{
	struct vnode *vp = ITOV(ip);
	struct ext2fs_htree_lookup_level *level;
	struct buf *bp;
	uint32_t next_hash;
	int idx = info->h_levels_num - 1;
	int levels = 0;

	for (;;) {
		level = &info->h_levels[idx];
		level->h_entry++;
		if (level->h_entry < level->h_entries +
		    ext2fs_htree_get_count(level->h_entries))
			break;
		if (idx == 0)
			return 0;
		idx--;
		levels++;
	}

	next_hash = ext2fs_htree_get_hash(level->h_entry);
	if ((hash & 1) == 0) {
		if (hash != (next_hash & ~1))
			return 0;
	}

	while (levels > 0) {
		levels--;
		if (ext2fs_blkatoff(vp, ext2fs_htree_get_block(level->h_entry) *
		    ip->i_e2fs->e2fs_bsize, NULL, &bp) != 0)
			return 0;
		level = &info->h_levels[idx + 1];
		brelse(level->h_bp, 0);
		level->h_bp = bp;
		level->h_entry = level->h_entries =
		    ((struct ext2fs_htree_node *)bp->b_data)->h_entries;
	}

	return 1;
}

static int
ext2fs_htree_find_leaf(struct inode *ip, const char *name, int namelen,
    uint32_t *hash, uint8_t *hash_ver,
    struct ext2fs_htree_lookup_info *info)
{
	struct vnode *vp;
	struct ext2fs *fs;/* F, G, and H are MD4 functions */
	struct m_ext2fs *m_fs;
	struct buf *bp = NULL;
	struct ext2fs_htree_root *rootp;
	struct ext2fs_htree_entry *entp, *start, *end, *middle, *found;
	struct ext2fs_htree_lookup_level *level_info;
	uint32_t hash_major = 0, hash_minor = 0;
	uint32_t levels, cnt;
	uint8_t hash_version;

	if (name == NULL || info == NULL)
		return -1;

	vp = ITOV(ip);
	fs = &(ip->i_e2fs->e2fs);
	m_fs = ip->i_e2fs;

	if (ext2fs_blkatoff(vp, 0, NULL, &bp) != 0)
		return -1;

	info->h_levels_num = 1;
	info->h_levels[0].h_bp = bp;
	rootp = (struct ext2fs_htree_root *)bp->b_data;
	if (rootp->h_info.h_hash_version != EXT2_HTREE_LEGACY &&
	    rootp->h_info.h_hash_version != EXT2_HTREE_HALF_MD4 &&
	    rootp->h_info.h_hash_version != EXT2_HTREE_TEA)
		goto error;

	hash_version = rootp->h_info.h_hash_version;
	if (hash_version <= EXT2_HTREE_TEA)
		hash_version += m_fs->e2fs_uhash;
	*hash_ver = hash_version;

	ext2fs_htree_hash(name, namelen, fs->e3fs_hash_seed,
	    hash_version, &hash_major, &hash_minor);
	*hash = hash_major;

	if ((levels = rootp->h_info.h_ind_levels) > 1)
		goto error;

	entp = (struct ext2fs_htree_entry *)(((char *)&rootp->h_info) +
	    rootp->h_info.h_info_len);

	if (ext2fs_htree_get_limit(entp) !=
	    ext2fs_htree_root_limit(ip, rootp->h_info.h_info_len))
		goto error;

	for (;;) {
		cnt = ext2fs_htree_get_count(entp);
		if (cnt == 0 || cnt > ext2fs_htree_get_limit(entp))
			goto error;

		start = entp + 1;
		end = entp + cnt - 1;
		while (start <= end) {
			middle = start + (end - start) / 2;
			if (ext2fs_htree_get_hash(middle) > hash_major)
				end = middle - 1;
			else
				start = middle + 1;
		}
		found = start - 1;

		level_info = &(info->h_levels[info->h_levels_num - 1]);
		level_info->h_bp = bp;
		level_info->h_entries = entp;
		level_info->h_entry = found;
		if (levels == 0)
			return (0);
		levels--;
		if (ext2fs_blkatoff(vp,
		    ext2fs_htree_get_block(found) * m_fs->e2fs_bsize,
		    NULL, &bp) != 0)
			goto error;
		entp = ((struct ext2fs_htree_node *)bp->b_data)->h_entries;
		info->h_levels_num++;
		info->h_levels[info->h_levels_num - 1].h_bp = bp;
	}

error:
	ext2fs_htree_release(info);
	return -1;
}

/*
 * Try to lookup a directory entry in HTree index
 */
int
ext2fs_htree_lookup(struct inode *ip, const char *name, int namelen,
    struct buf **bpp, int *entryoffp, doff_t *offp,
    doff_t *prevoffp, doff_t *endusefulp, struct ext2fs_searchslot *ss)
{
	struct vnode *vp;
	struct ext2fs_htree_lookup_info info;
	struct ext2fs_htree_entry *leaf_node;
	struct m_ext2fs *m_fs;
	struct buf *bp;
	uint32_t blk;
	uint32_t dirhash;
	uint32_t bsize;
	uint8_t hash_version;
	int search_next;

	m_fs = ip->i_e2fs;
	bsize = m_fs->e2fs_bsize;
	vp = ITOV(ip);

	/* TODO: print error msg because we don't lookup '.' and '..' */

	memset(&info, 0, sizeof(info));
	if (ext2fs_htree_find_leaf(ip, name, namelen, &dirhash,
	    &hash_version, &info)) {
		return -1;
	}

	do {
		leaf_node = info.h_levels[info.h_levels_num - 1].h_entry;
		blk = ext2fs_htree_get_block(leaf_node);
		if (ext2fs_blkatoff(vp, blk * bsize, NULL, &bp) != 0) {
			ext2fs_htree_release(&info);
			return -1;
		}

		*offp = blk * bsize;
		*entryoffp = 0;
		*prevoffp = blk * bsize;
		*endusefulp = blk * bsize;

		if (ss->slotstatus == NONE) {
			ss->slotoffset = -1;
			ss->slotfreespace = 0;
		}

		int found;
		if (ext2fs_search_dirblock(ip, bp->b_data, &found,
		    name, namelen, entryoffp, offp, prevoffp,
		    endusefulp, ss) != 0) {
			brelse(bp, 0);
			ext2fs_htree_release(&info);
			return -1;
		}

		if (found) {
			*bpp = bp;
			ext2fs_htree_release(&info);
			return 0;
		}

		brelse(bp,0);
		search_next = ext2fs_htree_check_next(ip, dirhash, name, &info);
	} while (search_next);

	ext2fs_htree_release(&info);
	return ENOENT;
}

File Added: src/sys/ufs/ext2fs/ext2fs_htree.h
/*	$NetBSD: ext2fs_htree.h,v 1.1 2016/06/24 17:21:30 christos Exp $	*/

/*-
 * Copyright (c) 2010, 2012 Zheng Liu <lz@freebsd.org>
 * Copyright (c) 2012, Vyacheslav Matyushin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: head/sys/fs/ext2fs/htree.h 262623 2014-02-28 21:25:32Z pfg $
 */
#ifndef _FS_EXT2FS_HTREE_H_
#define	_FS_EXT2FS_HTREE_H_

/* EXT3 HTree directory indexing */

#define	EXT2_HTREE_LEGACY		0
#define	EXT2_HTREE_HALF_MD4		1
#define	EXT2_HTREE_TEA			2
#define	EXT2_HTREE_LEGACY_UNSIGNED	3
#define	EXT2_HTREE_HALF_MD4_UNSIGNED	4
#define	EXT2_HTREE_TEA_UNSIGNED		5

#define	EXT2_HTREE_EOF 0x7FFFFFFF

struct ext2fs_fake_direct {
	uint32_t e2d_ino;	/* inode number of entry */
	uint16_t e2d_reclen;	/* length of this record */
	uint8_t  e2d_namlen;	/* length of string in d_name */
	uint8_t  e2d_type;	/* file type */
};

struct ext2fs_htree_count {
	uint16_t h_entries_max;
	uint16_t h_entries_num;
};

struct ext2fs_htree_entry {
	uint32_t h_hash;
	uint32_t h_blk;
};

struct ext2fs_htree_root_info {
	uint32_t h_reserved1;
	uint8_t  h_hash_version;
	uint8_t  h_info_len;
	uint8_t  h_ind_levels;
	uint8_t  h_reserved2;
};

struct ext2fs_htree_root {
	struct ext2fs_fake_direct h_dot;
	char h_dot_name[4];
	struct ext2fs_fake_direct h_dotdot;
	char h_dotdot_name[4];
	struct ext2fs_htree_root_info h_info;
	struct ext2fs_htree_entry h_entries[0];
};

struct ext2fs_htree_node {
	struct ext2fs_fake_direct h_fake_dirent;
	struct ext2fs_htree_entry h_entries[0];
};

struct ext2fs_htree_lookup_level {
	struct buf *h_bp;
	struct ext2fs_htree_entry *h_entries;
	struct ext2fs_htree_entry *h_entry;
};

struct ext2fs_htree_lookup_info {
	struct ext2fs_htree_lookup_level h_levels[2];
	uint32_t h_levels_num;
};

struct ext2fs_htree_sort_entry {
	uint16_t h_offset;
	uint16_t h_size;
	uint32_t h_hash;
};

#endif /* !_FS_EXT2FS_HTREE_H_ */

cvs diff -r1.79 -r1.80 src/sys/ufs/ext2fs/ext2fs_lookup.c (expand / switch to unified diff)

--- src/sys/ufs/ext2fs/ext2fs_lookup.c 2016/01/12 21:29:29 1.79
+++ src/sys/ufs/ext2fs/ext2fs_lookup.c 2016/06/24 17:21:30 1.80
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ext2fs_lookup.c,v 1.79 2016/01/12 21:29:29 riastradh Exp $ */ 1/* $NetBSD: ext2fs_lookup.c,v 1.80 2016/06/24 17:21:30 christos Exp $ */
2 2
3/* 3/*
4 * Modified for NetBSD 1.2E 4 * Modified for NetBSD 1.2E
5 * May 1997, Manuel Bouyer 5 * May 1997, Manuel Bouyer
6 * Laboratoire d'informatique de Paris VI 6 * Laboratoire d'informatique de Paris VI
7 */ 7 */
8/* 8/*
9 * modified for Lites 1.1 9 * modified for Lites 1.1
10 * 10 *
11 * Aug 1995, Godmar Back (gback@cs.utah.edu) 11 * Aug 1995, Godmar Back (gback@cs.utah.edu)
12 * University of Utah, Department of Computer Science 12 * University of Utah, Department of Computer Science
13 */ 13 */
14/* 14/*
@@ -38,48 +38,49 @@ @@ -38,48 +38,49 @@
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE. 45 * SUCH DAMAGE.
46 * 46 *
47 * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 47 * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94
48 */ 48 */
49 49
50#include <sys/cdefs.h> 50#include <sys/cdefs.h>
51__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.79 2016/01/12 21:29:29 riastradh Exp $"); 51__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.80 2016/06/24 17:21:30 christos Exp $");
52 52
53#include <sys/param.h> 53#include <sys/param.h>
54#include <sys/systm.h> 54#include <sys/systm.h>
55#include <sys/namei.h> 55#include <sys/namei.h>
56#include <sys/buf.h> 56#include <sys/buf.h>
57#include <sys/file.h> 57#include <sys/file.h>
58#include <sys/mount.h> 58#include <sys/mount.h>
59#include <sys/vnode.h> 59#include <sys/vnode.h>
60#include <sys/kmem.h> 60#include <sys/kmem.h>
61#include <sys/malloc.h> 61#include <sys/malloc.h>
62#include <sys/dirent.h> 62#include <sys/dirent.h>
63#include <sys/kauth.h> 63#include <sys/kauth.h>
64#include <sys/proc.h> 64#include <sys/proc.h>
65 65
66#include <ufs/ufs/inode.h> 66#include <ufs/ufs/inode.h>
67#include <ufs/ufs/ufsmount.h> 67#include <ufs/ufs/ufsmount.h>
68#include <ufs/ufs/ufs_extern.h> 68#include <ufs/ufs/ufs_extern.h>
69 69
70#include <ufs/ext2fs/ext2fs_extern.h> 70#include <ufs/ext2fs/ext2fs_extern.h>
71#include <ufs/ext2fs/ext2fs_dir.h> 71#include <ufs/ext2fs/ext2fs_dir.h>
72#include <ufs/ext2fs/ext2fs.h> 72#include <ufs/ext2fs/ext2fs.h>
 73#include <ufs/ext2fs/ext2fs_htree.h>
73 74
74#include <miscfs/genfs/genfs.h> 75#include <miscfs/genfs/genfs.h>
75 76
76extern int dirchk; 77extern int dirchk;
77 78
78static void ext2fs_dirconv2ffs(struct ext2fs_direct *e2dir, 79static void ext2fs_dirconv2ffs(struct ext2fs_direct *e2dir,
79 struct dirent *ffsdir); 80 struct dirent *ffsdir);
80static int ext2fs_dirbadentry(struct vnode *dp, 81static int ext2fs_dirbadentry(struct vnode *dp,
81 struct ext2fs_direct *de, 82 struct ext2fs_direct *de,
82 int entryoffsetinblock); 83 int entryoffsetinblock);
83 84
84/* 85/*
85 * the problem that is tackled below is the fact that FFS 86 * the problem that is tackled below is the fact that FFS
@@ -107,26 +108,33 @@ ext2fs_dirconv2ffs(struct ext2fs_direct  @@ -107,26 +108,33 @@ ext2fs_dirconv2ffs(struct ext2fs_direct
107 if (e2dir->e2d_namlen > MAXNAMLEN) 108 if (e2dir->e2d_namlen > MAXNAMLEN)
108 panic("ext2fs: e2dir->e2d_namlen"); 109 panic("ext2fs: e2dir->e2d_namlen");
109#endif 110#endif
110#endif 111#endif
111 strncpy(ffsdir->d_name, e2dir->e2d_name, ffsdir->d_namlen); 112 strncpy(ffsdir->d_name, e2dir->e2d_name, ffsdir->d_namlen);
112 113
113 /* Godmar thinks: since e2dir->e2d_reclen can be big and means 114 /* Godmar thinks: since e2dir->e2d_reclen can be big and means
114 nothing anyway, we compute our own reclen according to what 115 nothing anyway, we compute our own reclen according to what
115 we think is right 116 we think is right
116 */ 117 */
117 ffsdir->d_reclen = _DIRENT_SIZE(ffsdir); 118 ffsdir->d_reclen = _DIRENT_SIZE(ffsdir);
118} 119}
119 120
 121static int
 122ext2fs_is_dot_entry(struct componentname *cnp)
 123{
 124 return cnp->cn_namelen <= 2 && cnp->cn_nameptr[0] == '.' &&
 125 (cnp->cn_nameptr[1] == '.' || cnp->cn_nameptr[1] == '\0');
 126}
 127
120/* 128/*
121 * Vnode op for reading directories. 129 * Vnode op for reading directories.
122 * 130 *
123 * Convert the on-disk entries to <sys/dirent.h> entries. 131 * Convert the on-disk entries to <sys/dirent.h> entries.
124 * the problem is that the conversion will blow up some entries by four bytes, 132 * the problem is that the conversion will blow up some entries by four bytes,
125 * so it can't be done in place. This is too bad. Right now the conversion is 133 * so it can't be done in place. This is too bad. Right now the conversion is
126 * done entry by entry, the converted entry is sent via uiomove. 134 * done entry by entry, the converted entry is sent via uiomove.
127 * 135 *
128 * XXX allocate a buffer, convert as many entries as possible, then send 136 * XXX allocate a buffer, convert as many entries as possible, then send
129 * the whole buffer to uiomove 137 * the whole buffer to uiomove
130 */ 138 */
131int 139int
132ext2fs_readdir(void *v) 140ext2fs_readdir(void *v)
@@ -261,47 +269,49 @@ ext2fs_readdir(void *v) @@ -261,47 +269,49 @@ ext2fs_readdir(void *v)
261int 269int
262ext2fs_lookup(void *v) 270ext2fs_lookup(void *v)
263{ 271{
264 struct vop_lookup_v2_args /* { 272 struct vop_lookup_v2_args /* {
265 struct vnode *a_dvp; 273 struct vnode *a_dvp;
266 struct vnode **a_vpp; 274 struct vnode **a_vpp;
267 struct componentname *a_cnp; 275 struct componentname *a_cnp;
268 } */ *ap = v; 276 } */ *ap = v;
269 struct vnode *vdp = ap->a_dvp; /* vnode for directory being searched */ 277 struct vnode *vdp = ap->a_dvp; /* vnode for directory being searched */
270 struct inode *dp = VTOI(vdp); /* inode for directory being searched */ 278 struct inode *dp = VTOI(vdp); /* inode for directory being searched */
271 struct buf *bp; /* a buffer of directory entries */ 279 struct buf *bp; /* a buffer of directory entries */
272 struct ext2fs_direct *ep; /* the current directory entry */ 280 struct ext2fs_direct *ep; /* the current directory entry */
273 int entryoffsetinblock; /* offset of ep in bp's buffer */ 281 int entryoffsetinblock; /* offset of ep in bp's buffer */
274 enum {NONE, COMPACT, FOUND} slotstatus; 282 enum ext2fs_slotstatus slotstatus;
275 doff_t slotoffset; /* offset of area with free space */ 283 doff_t slotoffset; /* offset of area with free space */
276 int slotsize; /* size of area at slotoffset */ 284 int slotsize; /* size of area at slotoffset */
277 int slotfreespace; /* amount of space free in slot */ 285 int slotfreespace; /* amount of space free in slot */
278 int slotneeded; /* size of the entry we're seeking */ 286 int slotneeded; /* size of the entry we're seeking */
279 int numdirpasses; /* strategy for directory search */ 287 int numdirpasses; /* strategy for directory search */
280 doff_t endsearch; /* offset to end directory search */ 288 doff_t endsearch; /* offset to end directory search */
281 doff_t prevoff; /* prev entry dp->i_offset */ 289 doff_t prevoff; /* prev entry dp->i_offset */
282 struct vnode *tdp; /* returned by vcache_get */ 290 struct vnode *tdp; /* returned by vcache_get */
283 doff_t enduseful; /* pointer past last used dir slot */ 291 doff_t enduseful; /* pointer past last used dir slot */
284 u_long bmask; /* block offset mask */ 292 u_long bmask; /* block offset mask */
285 int namlen, error; 293 int namlen, error;
286 struct vnode **vpp = ap->a_vpp; 294 struct vnode **vpp = ap->a_vpp;
287 struct componentname *cnp = ap->a_cnp; 295 struct componentname *cnp = ap->a_cnp;
288 kauth_cred_t cred = cnp->cn_cred; 296 kauth_cred_t cred = cnp->cn_cred;
289 int flags; 297 int flags;
290 int nameiop = cnp->cn_nameiop; 298 int nameiop = cnp->cn_nameiop;
291 struct ufsmount *ump = dp->i_ump; 299 struct ufsmount *ump = dp->i_ump;
292 int dirblksiz = ump->um_dirblksiz; 300 int dirblksiz = ump->um_dirblksiz;
293 ino_t foundino; 301 ino_t foundino;
294 struct ufs_lookup_results *results; 302 struct ufs_lookup_results *results;
 303 doff_t i_offset; /* cached i_offset value */
 304 struct ext2fs_searchslot ss;
295 305
296 flags = cnp->cn_flags; 306 flags = cnp->cn_flags;
297 307
298 bp = NULL; 308 bp = NULL;
299 slotoffset = -1; 309 slotoffset = -1;
300 *vpp = NULL; 310 *vpp = NULL;
301 311
302 /* 312 /*
303 * Produce the auxiliary lookup results into i_crap. Increment 313 * Produce the auxiliary lookup results into i_crap. Increment
304 * its serial number so elsewhere we can tell if we're using 314 * its serial number so elsewhere we can tell if we're using
305 * stale results. This should not be done this way. XXX. 315 * stale results. This should not be done this way. XXX.
306 */ 316 */
307 results = &dp->i_crap; 317 results = &dp->i_crap;
@@ -362,26 +372,57 @@ ext2fs_lookup(void *v) @@ -362,26 +372,57 @@ ext2fs_lookup(void *v)
362 numdirpasses = 1; 372 numdirpasses = 1;
363 } else { 373 } else {
364 results->ulr_offset = results->ulr_diroff; 374 results->ulr_offset = results->ulr_diroff;
365 if ((entryoffsetinblock = results->ulr_offset & bmask) && 375 if ((entryoffsetinblock = results->ulr_offset & bmask) &&
366 (error = ext2fs_blkatoff(vdp, (off_t)results->ulr_offset, NULL, &bp))) 376 (error = ext2fs_blkatoff(vdp, (off_t)results->ulr_offset, NULL, &bp)))
367 return (error); 377 return (error);
368 numdirpasses = 2; 378 numdirpasses = 2;
369 namecache_count_2passes(); 379 namecache_count_2passes();
370 } 380 }
371 prevoff = results->ulr_offset; 381 prevoff = results->ulr_offset;
372 endsearch = roundup(ext2fs_size(dp), dirblksiz); 382 endsearch = roundup(ext2fs_size(dp), dirblksiz);
373 enduseful = 0; 383 enduseful = 0;
374 384
 385 /*
 386 * Try to lookup dir entry using htree directory index.
 387 *
 388 * If we got an error or we want to find '.' or '..' entry,
 389 * we will fall back to linear search.
 390 */
 391 if (ext2fs_htree_has_idx(dp) && ext2fs_is_dot_entry(cnp)) {
 392 numdirpasses = 1;
 393 entryoffsetinblock = 0;
 394
 395 int htree_lookup_ret = ext2fs_htree_lookup(dp, cnp->cn_nameptr,
 396 cnp->cn_namelen, &bp, &entryoffsetinblock, &i_offset,
 397 &prevoff, &enduseful, &ss);
 398 switch (htree_lookup_ret) {
 399 case 0:
 400 ep = (struct ext2fs_direct*)((char *)bp->b_data +
 401 (i_offset & bmask));
 402 foundino = ep->e2d_ino;
 403 goto found;
 404 case ENOENT:
 405 i_offset = roundup2(dp->i_size, dp->i_e2fs->e2fs_bsize);
 406 goto notfound;
 407 default:
 408 /*
 409 * Something failed; just fallback to do a linear
 410 * search.
 411 */
 412 break;
 413 }
 414 }
 415
375searchloop: 416searchloop:
376 while (results->ulr_offset < endsearch) { 417 while (results->ulr_offset < endsearch) {
377 if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) 418 if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
378 preempt(); 419 preempt();
379 /* 420 /*
380 * If necessary, get the next directory block. 421 * If necessary, get the next directory block.
381 */ 422 */
382 if ((results->ulr_offset & bmask) == 0) { 423 if ((results->ulr_offset & bmask) == 0) {
383 if (bp != NULL) 424 if (bp != NULL)
384 brelse(bp, 0); 425 brelse(bp, 0);
385 error = ext2fs_blkatoff(vdp, (off_t)results->ulr_offset, NULL, 426 error = ext2fs_blkatoff(vdp, (off_t)results->ulr_offset, NULL,
386 &bp); 427 &bp);
387 if (error != 0) 428 if (error != 0)
@@ -463,27 +504,27 @@ searchloop: @@ -463,27 +504,27 @@ searchloop:
463 * directory buffer. 504 * directory buffer.
464 */ 505 */
465 foundino = fs2h32(ep->e2d_ino); 506 foundino = fs2h32(ep->e2d_ino);
466 results->ulr_reclen = fs2h16(ep->e2d_reclen); 507 results->ulr_reclen = fs2h16(ep->e2d_reclen);
467 goto found; 508 goto found;
468 } 509 }
469 } 510 }
470 prevoff = results->ulr_offset; 511 prevoff = results->ulr_offset;
471 results->ulr_offset += fs2h16(ep->e2d_reclen); 512 results->ulr_offset += fs2h16(ep->e2d_reclen);
472 entryoffsetinblock += fs2h16(ep->e2d_reclen); 513 entryoffsetinblock += fs2h16(ep->e2d_reclen);
473 if (ep->e2d_ino) 514 if (ep->e2d_ino)
474 enduseful = results->ulr_offset; 515 enduseful = results->ulr_offset;
475 } 516 }
476/* notfound: */ 517notfound:
477 /* 518 /*
478 * If we started in the middle of the directory and failed 519 * If we started in the middle of the directory and failed
479 * to find our target, we must check the beginning as well. 520 * to find our target, we must check the beginning as well.
480 */ 521 */
481 if (numdirpasses == 2) { 522 if (numdirpasses == 2) {
482 numdirpasses--; 523 numdirpasses--;
483 results->ulr_offset = 0; 524 results->ulr_offset = 0;
484 endsearch = results->ulr_diroff; 525 endsearch = results->ulr_diroff;
485 goto searchloop; 526 goto searchloop;
486 } 527 }
487 if (bp != NULL) 528 if (bp != NULL)
488 brelse(bp, 0); 529 brelse(bp, 0);
489 /* 530 /*
@@ -656,26 +697,116 @@ found: @@ -656,26 +697,116 @@ found:
656 &foundino, sizeof(foundino), &tdp); 697 &foundino, sizeof(foundino), &tdp);
657 if (error) 698 if (error)
658 return (error); 699 return (error);
659 *vpp = tdp; 700 *vpp = tdp;
660 } 701 }
661 702
662 /* 703 /*
663 * Insert name into cache if appropriate. 704 * Insert name into cache if appropriate.
664 */ 705 */
665 cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); 706 cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
666 return 0; 707 return 0;
667} 708}
668 709
 710int
 711ext2fs_search_dirblock(struct inode *ip, void *data, int *foundp,
 712 const char *name, int namelen, int *entryoffsetinblockp,
 713 doff_t *offp, doff_t *prevoffp, doff_t *endusefulp,
 714 struct ext2fs_searchslot *ssp)
 715{
 716 struct vnode *vdp = ITOV(ip);
 717 struct ext2fs_direct *ep, *top;
 718 uint32_t bsize = ip->i_e2fs->e2fs_bsize;
 719 int offset = *entryoffsetinblockp;
 720 int namlen;
 721
 722 ep = (void *)((char *)data + offset);
 723 top = (void *)((char *)data + bsize - EXT2_DIR_REC_LEN(0));
 724
 725 while (ep < top) {
 726 /*
 727 * Full validation checks are slow, so we only check
 728 * enough to insure forward progress through the
 729 * directory. Complete checks can be run by setting
 730 * "vfs.e2fs.dirchk" to be true.
 731 */
 732 if (ep->e2d_reclen == 0 ||
 733 (dirchk && ext2fs_dirbadentry(vdp, ep, offset))) {
 734 int i;
 735 ufs_dirbad(ip, *offp, "mangled entry");
 736 i = bsize - (offset & (bsize - 1));
 737 *offp += i;
 738 offset += i;
 739 continue;
 740 }
 741
 742 /*
 743 * If an appropriate sized slot has not yet been found,
 744 * check to see if one is available. Also accumulate space
 745 * in the current block so that we can determine if
 746 * compaction is viable.
 747 */
 748 if (ssp->slotstatus != FOUND) {
 749 int size = ep->e2d_reclen;
 750
 751 if (ep->e2d_ino != 0)
 752 size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
 753 if (size >= ssp->slotneeded) {
 754 ssp->slotstatus = FOUND;
 755 ssp->slotoffset = *offp;
 756 ssp->slotsize = ep->e2d_reclen;
 757 } else if (size > 0 && ssp->slotstatus == NONE) {
 758 ssp->slotfreespace += size;
 759 if (ssp->slotoffset == -1)
 760 ssp->slotoffset = *offp;
 761 if (ssp->slotfreespace >= ssp->slotneeded) {
 762 ssp->slotstatus = COMPACT;
 763 ssp->slotsize = *offp + ep->e2d_reclen -
 764 ssp->slotoffset;
 765 }
 766 }
 767 }
 768
 769 /*
 770 * Check for a name match.
 771 */
 772 if (ep->e2d_ino) {
 773 namlen = ep->e2d_namlen;
 774 if (namlen == namelen &&
 775 !memcmp(name, ep->e2d_name, (unsigned)namlen)) {
 776 /*
 777 * Save directory entry's inode number and
 778 * reclen in ndp->ni_ufs area, and release
 779 * directory buffer.
 780 */
 781 *foundp = 1;
 782 return 0;
 783 }
 784 }
 785 *prevoffp = *offp;
 786 *offp += ep->e2d_reclen;
 787 offset += ep->e2d_reclen;
 788 *entryoffsetinblockp = offset;
 789 if (ep->e2d_ino)
 790 *endusefulp = *offp;
 791 /*
 792 * Get pointer to the next entry.
 793 */
 794 ep = (void *)((char *)data + offset);
 795 }
 796
 797 return 0;
 798}
 799
669/* 800/*
670 * Do consistency checking on a directory entry: 801 * Do consistency checking on a directory entry:
671 * record length must be multiple of 4 802 * record length must be multiple of 4
672 * entry must fit in rest of its dirblksize block 803 * entry must fit in rest of its dirblksize block
673 * record must be large enough to contain entry 804 * record must be large enough to contain entry
674 * name is not longer than EXT2FS_MAXNAMLEN 805 * name is not longer than EXT2FS_MAXNAMLEN
675 * name must be as long as advertised, and null terminated 806 * name must be as long as advertised, and null terminated
676 */ 807 */
677/* 808/*
678 * changed so that it confirms to ext2fs_check_dir_entry 809 * changed so that it confirms to ext2fs_check_dir_entry
679 */ 810 */
680static int 811static int
681ext2fs_dirbadentry(struct vnode *dp, struct ext2fs_direct *de, 812ext2fs_dirbadentry(struct vnode *dp, struct ext2fs_direct *de,