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
--- 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 */ |
233 | struct m_ext2fs { | | 233 | struct 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 |
--- 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 | |
109 | struct ext2fs_direct { | | 109 | struct 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 | |
| | | 117 | enum ext2fs_slotstatus { |
| | | 118 | NONE, |
| | | 119 | COMPACT, |
| | | 120 | FOUND |
| | | 121 | }; |
| | | 122 | |
| | | 123 | struct 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) |
169 | struct ext2fs_dirtemplate { | | 183 | struct 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_ */ |
--- 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; |
68 | struct inode; | | 68 | struct inode; |
69 | struct mount; | | 69 | struct mount; |
70 | struct nameidata; | | 70 | struct nameidata; |
71 | struct lwp; | | 71 | struct lwp; |
72 | struct proc; | | 72 | struct proc; |
73 | struct statvfs; | | 73 | struct statvfs; |
74 | struct timeval; | | 74 | struct timeval; |
75 | struct ufsmount; | | 75 | struct ufsmount; |
76 | struct uio; | | 76 | struct uio; |
77 | struct vnode; | | 77 | struct vnode; |
78 | struct mbuf; | | 78 | struct mbuf; |
79 | struct componentname; | | 79 | struct componentname; |
80 | struct ufs_lookup_results; | | 80 | struct ufs_lookup_results; |
| | | 81 | struct ext2fs_searchslot; |
81 | | | 82 | |
82 | extern struct pool ext2fs_inode_pool; /* memory pool for inodes */ | | 83 | extern struct pool ext2fs_inode_pool; /* memory pool for inodes */ |
83 | extern struct pool ext2fs_dinode_pool; /* memory pool for dinodes */ | | 84 | extern 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 */ |
92 | int ext2fs_alloc(struct inode *, daddr_t, daddr_t , kauth_cred_t, | | 93 | int 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 */ |
111 | uint64_t ext2fs_size(struct inode *); | | 112 | uint64_t ext2fs_size(struct inode *); |
112 | int ext2fs_setsize(struct inode *, uint64_t); | | 113 | int ext2fs_setsize(struct inode *, uint64_t); |
113 | uint64_t ext2fs_nblock(struct inode *); | | 114 | uint64_t ext2fs_nblock(struct inode *); |
114 | int ext2fs_setnblock(struct inode *, uint64_t); | | 115 | int ext2fs_setnblock(struct inode *, uint64_t); |
115 | int ext2fs_update(struct vnode *, const struct timespec *, | | 116 | int ext2fs_update(struct vnode *, const struct timespec *, |
116 | const struct timespec *, int); | | 117 | const struct timespec *, int); |
117 | int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t); | | 118 | int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t); |
118 | int ext2fs_inactive(void *); | | 119 | int ext2fs_inactive(void *); |
119 | | | 120 | |
120 | /* ext2fs_lookup.c */ | | 121 | /* ext2fs_lookup.c */ |
121 | int ext2fs_readdir(void *); | | 122 | int ext2fs_readdir(void *); |
122 | int ext2fs_lookup(void *); | | 123 | int ext2fs_lookup(void *); |
| | | 124 | int ext2fs_search_dirblock(struct inode *, void *, int *, |
| | | 125 | const char *, int , int *, doff_t *, doff_t *, doff_t *, |
| | | 126 | struct ext2fs_searchslot *); |
123 | int ext2fs_direnter(struct inode *, struct vnode *, | | 127 | int ext2fs_direnter(struct inode *, struct vnode *, |
124 | const struct ufs_lookup_results *, | | 128 | const struct ufs_lookup_results *, |
125 | struct componentname *); | | 129 | struct componentname *); |
126 | int ext2fs_dirremove(struct vnode *, const struct ufs_lookup_results *, | | 130 | int ext2fs_dirremove(struct vnode *, const struct ufs_lookup_results *, |
127 | struct componentname *); | | 131 | struct componentname *); |
128 | int ext2fs_dirrewrite(struct inode *, const struct ufs_lookup_results *, | | 132 | int ext2fs_dirrewrite(struct inode *, const struct ufs_lookup_results *, |
129 | struct inode *, struct componentname *); | | 133 | struct inode *, struct componentname *); |
130 | int ext2fs_dirempty(struct inode *, ino_t, kauth_cred_t); | | 134 | int ext2fs_dirempty(struct inode *, ino_t, kauth_cred_t); |
131 | | | 135 | |
132 | /* ext2fs_subr.c */ | | 136 | /* ext2fs_subr.c */ |
133 | int ext2fs_blkatoff(struct vnode *, off_t, char **, struct buf **); | | 137 | int ext2fs_blkatoff(struct vnode *, off_t, char **, struct buf **); |
134 | void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int); | | 138 | void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int); |
135 | void ext2fs_itimes(struct inode *, const struct timespec *, | | 139 | void ext2fs_itimes(struct inode *, const struct timespec *, |
| @@ -162,22 +166,31 @@ int ext2fs_link(void *); | | | @@ -162,22 +166,31 @@ int ext2fs_link(void *); |
162 | int ext2fs_rename(void *); | | 166 | int ext2fs_rename(void *); |
163 | int ext2fs_mkdir(void *); | | 167 | int ext2fs_mkdir(void *); |
164 | int ext2fs_rmdir(void *); | | 168 | int ext2fs_rmdir(void *); |
165 | int ext2fs_symlink(void *); | | 169 | int ext2fs_symlink(void *); |
166 | int ext2fs_readlink(void *); | | 170 | int ext2fs_readlink(void *); |
167 | int ext2fs_advlock(void *); | | 171 | int ext2fs_advlock(void *); |
168 | int ext2fs_fsync(void *); | | 172 | int ext2fs_fsync(void *); |
169 | int ext2fs_vinit(struct mount *, int (**specops)(void *), | | 173 | int ext2fs_vinit(struct mount *, int (**specops)(void *), |
170 | int (**fifoops)(void *), struct vnode **); | | 174 | int (**fifoops)(void *), struct vnode **); |
171 | int ext2fs_makeinode(int, struct vnode *, struct vnode **, | | 175 | int ext2fs_makeinode(int, struct vnode *, struct vnode **, |
172 | struct componentname *cnp); | | 176 | struct componentname *cnp); |
173 | int ext2fs_reclaim(void *); | | 177 | int ext2fs_reclaim(void *); |
174 | | | 178 | |
| | | 179 | /* ext2fs_hash.c */ |
| | | 180 | int ext2fs_htree_hash(const char *, int, uint32_t *, int, uint32_t *, |
| | | 181 | uint32_t *); |
| | | 182 | |
| | | 183 | /* ext2fs_htree.c */ |
| | | 184 | int ext2fs_htree_has_idx(struct inode *); |
| | | 185 | int 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 | |
179 | extern int (**ext2fs_vnodeop_p)(void *); | | 192 | extern int (**ext2fs_vnodeop_p)(void *); |
180 | extern int (**ext2fs_specop_p)(void *); | | 193 | extern int (**ext2fs_specop_p)(void *); |
181 | extern int (**ext2fs_fifoop_p)(void *); | | 194 | extern int (**ext2fs_fifoop_p)(void *); |
182 | | | 195 | |
183 | #endif /* !_UFS_EXT2FS_EXT2FS_EXTERN_H_ */ | | 196 | #endif /* !_UFS_EXT2FS_EXT2FS_EXTERN_H_ */ |
/* $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;
}
/* $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_ */
/* $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;
}
/* $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_ */
--- 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 | |
76 | extern int dirchk; | | 77 | extern int dirchk; |
77 | | | 78 | |
78 | static void ext2fs_dirconv2ffs(struct ext2fs_direct *e2dir, | | 79 | static void ext2fs_dirconv2ffs(struct ext2fs_direct *e2dir, |
79 | struct dirent *ffsdir); | | 80 | struct dirent *ffsdir); |
80 | static int ext2fs_dirbadentry(struct vnode *dp, | | 81 | static 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 | |
| | | 121 | static int |
| | | 122 | ext2fs_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 | */ |
131 | int | | 139 | int |
132 | ext2fs_readdir(void *v) | | 140 | ext2fs_readdir(void *v) |
| @@ -261,47 +269,49 @@ ext2fs_readdir(void *v) | | | @@ -261,47 +269,49 @@ ext2fs_readdir(void *v) |
261 | int | | 269 | int |
262 | ext2fs_lookup(void *v) | | 270 | ext2fs_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 | |
375 | searchloop: | | 416 | searchloop: |
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: */ | | 517 | notfound: |
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 | |
| | | 710 | int |
| | | 711 | ext2fs_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 | */ |
680 | static int | | 811 | static int |
681 | ext2fs_dirbadentry(struct vnode *dp, struct ext2fs_direct *de, | | 812 | ext2fs_dirbadentry(struct vnode *dp, struct ext2fs_direct *de, |