ext2_lookup.c (ceae90c295a309e0196ef7e7e0456f27a0eefb85) ext2_lookup.c (91f5a4670fecd56003b04db85b8abbe63a5ee4eb)
1/*-
2 * modified for Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1989, 1993

--- 99 unchanged lines hidden (view full) ---

108 EXT2_FT_UNKNOWN, /* unused */
109 EXT2_FT_UNKNOWN, /* DT_WHT */
110};
111#define DTTOFT(dt) \
112 ((dt) < nitems(dt_to_ext2_ft) ? dt_to_ext2_ft[(dt)] : EXT2_FT_UNKNOWN)
113
114static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de,
115 int entryoffsetinblock);
1/*-
2 * modified for Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1989, 1993

--- 99 unchanged lines hidden (view full) ---

108 EXT2_FT_UNKNOWN, /* unused */
109 EXT2_FT_UNKNOWN, /* DT_WHT */
110};
111#define DTTOFT(dt) \
112 ((dt) < nitems(dt_to_ext2_ft) ? dt_to_ext2_ft[(dt)] : EXT2_FT_UNKNOWN)
113
114static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de,
115 int entryoffsetinblock);
116static int ext2_is_dot_entry(struct componentname *cnp);
116static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp,
117 struct componentname *cnp, ino_t *dd_ino);
118
117static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp,
118 struct componentname *cnp, ino_t *dd_ino);
119
120static int
121ext2_is_dot_entry(struct componentname *cnp)
122{
123 if (cnp->cn_namelen <= 2 && cnp->cn_nameptr[0] == '.' &&
124 (cnp->cn_nameptr[1] == '.' || cnp->cn_nameptr[1] == '0'))
125 return (1);
126 return (0);
127}
128
119/*
120 * Vnode op for reading directories.
121 *
122 * This function has to convert directory entries from the on-disk
123 * format to the format defined by <sys/dirent.h>. Unfortunately, the
124 * conversion will blow up some entries by four bytes, so it can't be
125 * done in place. Instead, the conversion is done entry by entry and
126 * the converted entry is sent via uiomove.

--- 155 unchanged lines hidden (view full) ---

282static int
283ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
284 ino_t *dd_ino)
285{
286 struct inode *dp; /* inode for directory being searched */
287 struct buf *bp; /* a buffer of directory entries */
288 struct ext2fs_direct_2 *ep; /* the current directory entry */
289 int entryoffsetinblock; /* offset of ep in bp's buffer */
129/*
130 * Vnode op for reading directories.
131 *
132 * This function has to convert directory entries from the on-disk
133 * format to the format defined by <sys/dirent.h>. Unfortunately, the
134 * conversion will blow up some entries by four bytes, so it can't be
135 * done in place. Instead, the conversion is done entry by entry and
136 * the converted entry is sent via uiomove.

--- 155 unchanged lines hidden (view full) ---

292static int
293ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp,
294 ino_t *dd_ino)
295{
296 struct inode *dp; /* inode for directory being searched */
297 struct buf *bp; /* a buffer of directory entries */
298 struct ext2fs_direct_2 *ep; /* the current directory entry */
299 int entryoffsetinblock; /* offset of ep in bp's buffer */
290 enum {NONE, COMPACT, FOUND} slotstatus;
291 doff_t slotoffset; /* offset of area with free space */
300 struct ext2fs_searchslot ss;
292 doff_t i_diroff; /* cached i_diroff value */
293 doff_t i_offset; /* cached i_offset value */
301 doff_t i_diroff; /* cached i_diroff value */
302 doff_t i_offset; /* cached i_offset value */
294 int slotsize; /* size of area at slotoffset */
295 int slotfreespace; /* amount of space free in slot */
296 int slotneeded; /* size of the entry we're seeking */
297 int numdirpasses; /* strategy for directory search */
298 doff_t endsearch; /* offset to end directory search */
299 doff_t prevoff; /* prev entry dp->i_offset */
300 struct vnode *pdp; /* saved dp during symlink work */
301 struct vnode *tdp; /* returned by VFS_VGET */
302 doff_t enduseful; /* pointer past last used dir slot */
303 u_long bmask; /* block offset mask */
303 int numdirpasses; /* strategy for directory search */
304 doff_t endsearch; /* offset to end directory search */
305 doff_t prevoff; /* prev entry dp->i_offset */
306 struct vnode *pdp; /* saved dp during symlink work */
307 struct vnode *tdp; /* returned by VFS_VGET */
308 doff_t enduseful; /* pointer past last used dir slot */
309 u_long bmask; /* block offset mask */
304 int namlen, error;
310 int error;
305 struct ucred *cred = cnp->cn_cred;
306 int flags = cnp->cn_flags;
307 int nameiop = cnp->cn_nameiop;
308 ino_t ino, ino1;
309 int ltype;
311 struct ucred *cred = cnp->cn_cred;
312 int flags = cnp->cn_flags;
313 int nameiop = cnp->cn_nameiop;
314 ino_t ino, ino1;
315 int ltype;
316 int entry_found = 0;
310
311 int DIRBLKSIZ = VTOI(vdp)->i_e2fs->e2fs_bsize;
312
313 if (vpp != NULL)
314 *vpp = NULL;
315
316 dp = VTOI(vdp);
317 bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
318restart:
319 bp = NULL;
317
318 int DIRBLKSIZ = VTOI(vdp)->i_e2fs->e2fs_bsize;
319
320 if (vpp != NULL)
321 *vpp = NULL;
322
323 dp = VTOI(vdp);
324 bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
325restart:
326 bp = NULL;
320 slotoffset = -1;
327 ss.slotoffset = -1;
321
322 /*
323 * We now have a segment name to search for, and a directory to search.
328
329 /*
330 * We now have a segment name to search for, and a directory to search.
324 */
325
326 /*
331 *
327 * Suppress search for slots unless creating
328 * file and at end of pathname, in which case
329 * we watch for a place to put the new file in
330 * case it doesn't already exist.
331 */
332 ino = 0;
333 i_diroff = dp->i_diroff;
332 * Suppress search for slots unless creating
333 * file and at end of pathname, in which case
334 * we watch for a place to put the new file in
335 * case it doesn't already exist.
336 */
337 ino = 0;
338 i_diroff = dp->i_diroff;
334 slotstatus = FOUND;
335 slotfreespace = slotsize = slotneeded = 0;
339 ss.slotstatus = FOUND;
340 ss.slotfreespace = ss.slotsize = ss.slotneeded = 0;
336 if ((nameiop == CREATE || nameiop == RENAME) &&
337 (flags & ISLASTCN)) {
341 if ((nameiop == CREATE || nameiop == RENAME) &&
342 (flags & ISLASTCN)) {
338 slotstatus = NONE;
339 slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen);
343 ss.slotstatus = NONE;
344 ss.slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen);
340 /* was
345 /* was
341 slotneeded = (sizeof(struct direct) - MAXNAMLEN +
346 ss.slotneeded = (sizeof(struct direct) - MAXNAMLEN +
342 cnp->cn_namelen + 3) &~ 3; */
343 }
344
345 /*
347 cnp->cn_namelen + 3) &~ 3; */
348 }
349
350 /*
351 * Try to lookup dir entry using htree directory index.
352 *
353 * If we got an error or we want to find '.' or '..' entry,
354 * we will fall back to linear search.
355 */
356 if (!ext2_is_dot_entry(cnp) && ext2_htree_has_idx(dp)) {
357 numdirpasses = 1;
358 entryoffsetinblock = 0;
359 switch (ext2_htree_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen,
360 &bp, &entryoffsetinblock, &i_offset, &prevoff,
361 &enduseful, &ss)) {
362 case 0:
363 ep = (struct ext2fs_direct_2 *)((char *)bp->b_data +
364 (i_offset & bmask));
365 goto foundentry;
366 case ENOENT:
367 i_offset = roundup2(dp->i_size, DIRBLKSIZ);
368 goto notfound;
369 default:
370 /*
371 * Something failed; just fallback to do a linear
372 * search.
373 */
374 break;
375 }
376 }
377
378 /*
346 * If there is cached information on a previous search of
347 * this directory, pick up where we last left off.
348 * We cache only lookups as these are the most common
349 * and have the greatest payoff. Caching CREATE has little
350 * benefit as it usually must search the entire directory
351 * to determine that the entry does not exist. Caching the
352 * location of the last DELETE or RENAME has not reduced
353 * profiling time and hence has been removed in the interest

--- 17 unchanged lines hidden (view full) ---

371 endsearch = roundup2(dp->i_size, DIRBLKSIZ);
372 enduseful = 0;
373
374searchloop:
375 while (i_offset < endsearch) {
376 /*
377 * If necessary, get the next directory block.
378 */
379 * If there is cached information on a previous search of
380 * this directory, pick up where we last left off.
381 * We cache only lookups as these are the most common
382 * and have the greatest payoff. Caching CREATE has little
383 * benefit as it usually must search the entire directory
384 * to determine that the entry does not exist. Caching the
385 * location of the last DELETE or RENAME has not reduced
386 * profiling time and hence has been removed in the interest

--- 17 unchanged lines hidden (view full) ---

404 endsearch = roundup2(dp->i_size, DIRBLKSIZ);
405 enduseful = 0;
406
407searchloop:
408 while (i_offset < endsearch) {
409 /*
410 * If necessary, get the next directory block.
411 */
379 if ((i_offset & bmask) == 0) {
380 if (bp != NULL)
381 brelse(bp);
382 if ((error =
383 ext2_blkatoff(vdp, (off_t)i_offset, NULL,
384 &bp)) != 0)
385 return (error);
386 entryoffsetinblock = 0;
387 }
412 if (bp != NULL)
413 brelse(bp);
414 error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp);
415 if (error != 0)
416 return (error);
417 entryoffsetinblock = 0;
388 /*
389 * If still looking for a slot, and at a DIRBLKSIZE
390 * boundary, have to start looking for free space again.
391 */
418 /*
419 * If still looking for a slot, and at a DIRBLKSIZE
420 * boundary, have to start looking for free space again.
421 */
392 if (slotstatus == NONE &&
422 if (ss.slotstatus == NONE &&
393 (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
423 (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
394 slotoffset = -1;
395 slotfreespace = 0;
424 ss.slotoffset = -1;
425 ss.slotfreespace = 0;
396 }
426 }
397 /*
398 * Get pointer to next entry.
399 * Full validation checks are slow, so we only check
400 * enough to insure forward progress through the
401 * directory. Complete checks can be run by setting
402 * "vfs.e2fs.dirchk" to be true.
403 */
404 ep = (struct ext2fs_direct_2 *)
405 ((char *)bp->b_data + entryoffsetinblock);
406 if (ep->e2d_reclen == 0 ||
407 (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) {
408 int i;
409 ext2_dirbad(dp, i_offset, "mangled entry");
410 i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1));
411 i_offset += i;
412 entryoffsetinblock += i;
413 continue;
427 error = ext2_search_dirblock(dp, bp->b_data, &entry_found,
428 cnp->cn_nameptr, cnp->cn_namelen,
429 &entryoffsetinblock, &i_offset, &prevoff,
430 &enduseful, &ss);
431 if (error != 0) {
432 brelse(bp);
433 return (error);
414 }
434 }
415
416 /*
417 * If an appropriate sized slot has not yet been found,
418 * check to see if one is available. Also accumulate space
419 * in the current block so that we can determine if
420 * compaction is viable.
421 */
422 if (slotstatus != FOUND) {
423 int size = ep->e2d_reclen;
424
425 if (ep->e2d_ino != 0)
426 size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
427 if (size > 0) {
428 if (size >= slotneeded) {
429 slotstatus = FOUND;
430 slotoffset = i_offset;
431 slotsize = ep->e2d_reclen;
432 } else if (slotstatus == NONE) {
433 slotfreespace += size;
434 if (slotoffset == -1)
435 slotoffset = i_offset;
436 if (slotfreespace >= slotneeded) {
437 slotstatus = COMPACT;
438 slotsize = i_offset +
439 ep->e2d_reclen - slotoffset;
440 }
441 }
442 }
435 if (entry_found) {
436 ep = (struct ext2fs_direct_2 *)((char *)bp->b_data +
437 (entryoffsetinblock & bmask));
438foundentry:
439 ino = ep->e2d_ino;
440 goto found;
443 }
441 }
444
445 /*
446 * Check for a name match.
447 */
448 if (ep->e2d_ino) {
449 namlen = ep->e2d_namlen;
450 if (namlen == cnp->cn_namelen &&
451 !bcmp(cnp->cn_nameptr, ep->e2d_name,
452 (unsigned)namlen)) {
453 /*
454 * Save directory entry's inode number and
455 * reclen in ndp->ni_ufs area, and release
456 * directory buffer.
457 */
458 ino = ep->e2d_ino;
459 goto found;
460 }
461 }
462 prevoff = i_offset;
463 i_offset += ep->e2d_reclen;
464 entryoffsetinblock += ep->e2d_reclen;
465 if (ep->e2d_ino)
466 enduseful = i_offset;
467 }
442 }
468/* notfound: */
443notfound:
469 /*
470 * If we started in the middle of the directory and failed
471 * to find our target, we must check the beginning as well.
472 */
473 if (numdirpasses == 2) {
474 numdirpasses--;
475 i_offset = 0;
476 endsearch = i_diroff;

--- 18 unchanged lines hidden (view full) ---

495 * Return an indication of where the new directory
496 * entry should be put. If we didn't find a slot,
497 * then set dp->i_count to 0 indicating
498 * that the new slot belongs at the end of the
499 * directory. If we found a slot, then the new entry
500 * can be put in the range from dp->i_offset to
501 * dp->i_offset + dp->i_count.
502 */
444 /*
445 * If we started in the middle of the directory and failed
446 * to find our target, we must check the beginning as well.
447 */
448 if (numdirpasses == 2) {
449 numdirpasses--;
450 i_offset = 0;
451 endsearch = i_diroff;

--- 18 unchanged lines hidden (view full) ---

470 * Return an indication of where the new directory
471 * entry should be put. If we didn't find a slot,
472 * then set dp->i_count to 0 indicating
473 * that the new slot belongs at the end of the
474 * directory. If we found a slot, then the new entry
475 * can be put in the range from dp->i_offset to
476 * dp->i_offset + dp->i_count.
477 */
503 if (slotstatus == NONE) {
478 if (ss.slotstatus == NONE) {
504 dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ);
505 dp->i_count = 0;
506 enduseful = dp->i_offset;
507 } else {
479 dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ);
480 dp->i_count = 0;
481 enduseful = dp->i_offset;
482 } else {
508 dp->i_offset = slotoffset;
509 dp->i_count = slotsize;
510 if (enduseful < slotoffset + slotsize)
511 enduseful = slotoffset + slotsize;
483 dp->i_offset = ss.slotoffset;
484 dp->i_count = ss.slotsize;
485 if (enduseful < ss.slotoffset + ss.slotsize)
486 enduseful = ss.slotoffset + ss.slotsize;
512 }
513 dp->i_endoff = roundup2(enduseful, DIRBLKSIZ);
514 /*
515 * We return with the directory locked, so that
516 * the parameters we set up above will still be
517 * valid if we actually decide to do a direnter().
518 * We return ni_vp == NULL to indicate that the entry
519 * does not currently exist; we leave a pointer to

--- 189 unchanged lines hidden (view full) ---

709 /*
710 * Insert name into cache if appropriate.
711 */
712 if (cnp->cn_flags & MAKEENTRY)
713 cache_enter(vdp, *vpp, cnp);
714 return (0);
715}
716
487 }
488 dp->i_endoff = roundup2(enduseful, DIRBLKSIZ);
489 /*
490 * We return with the directory locked, so that
491 * the parameters we set up above will still be
492 * valid if we actually decide to do a direnter().
493 * We return ni_vp == NULL to indicate that the entry
494 * does not currently exist; we leave a pointer to

--- 189 unchanged lines hidden (view full) ---

684 /*
685 * Insert name into cache if appropriate.
686 */
687 if (cnp->cn_flags & MAKEENTRY)
688 cache_enter(vdp, *vpp, cnp);
689 return (0);
690}
691
692int
693ext2_search_dirblock(struct inode *ip, void *data, int *foundp,
694 const char *name, int namelen, int *entryoffsetinblockp,
695 doff_t *offp, doff_t *prevoffp, doff_t *endusefulp,
696 struct ext2fs_searchslot *ssp)
697{
698 struct vnode *vdp;
699 struct ext2fs_direct_2 *ep, *top;
700 uint32_t bsize = ip->i_e2fs->e2fs_bsize;
701 int offset = *entryoffsetinblockp;
702 int namlen;
703
704 vdp = ITOV(ip);
705
706 ep = (struct ext2fs_direct_2 *)((char *)data + offset);
707 top = (struct ext2fs_direct_2 *)((char *)data +
708 bsize - EXT2_DIR_REC_LEN(0));
709
710 while (ep < top) {
711 /*
712 * Full validation checks are slow, so we only check
713 * enough to insure forward progress through the
714 * directory. Complete checks can be run by setting
715 * "vfs.e2fs.dirchk" to be true.
716 */
717 if (ep->e2d_reclen == 0 ||
718 (dirchk && ext2_dirbadentry(vdp, ep, offset))) {
719 int i;
720 ext2_dirbad(ip, *offp, "mangled entry");
721 i = bsize - (offset & (bsize - 1));
722 *offp += i;
723 offset += i;
724 continue;
725 }
726
727 /*
728 * If an appropriate sized slot has not yet been found,
729 * check to see if one is available. Also accumulate space
730 * in the current block so that we can determine if
731 * compaction is viable.
732 */
733 if (ssp->slotstatus != FOUND) {
734 int size = ep->e2d_reclen;
735
736 if (ep->e2d_ino != 0)
737 size -= EXT2_DIR_REC_LEN(ep->e2d_namlen);
738 if (size > 0) {
739 if (size >= ssp->slotneeded) {
740 ssp->slotstatus = FOUND;
741 ssp->slotoffset = *offp;
742 ssp->slotsize = ep->e2d_reclen;
743 } else if (ssp->slotstatus == NONE) {
744 ssp->slotfreespace += size;
745 if (ssp->slotoffset == -1)
746 ssp->slotoffset = *offp;
747 if (ssp->slotfreespace >= ssp->slotneeded) {
748 ssp->slotstatus = COMPACT;
749 ssp->slotsize = *offp +
750 ep->e2d_reclen -
751 ssp->slotoffset;
752 }
753 }
754 }
755 }
756
757 /*
758 * Check for a name match.
759 */
760 if (ep->e2d_ino) {
761 namlen = ep->e2d_namlen;
762 if (namlen == namelen &&
763 !bcmp(name, ep->e2d_name, (unsigned)namlen)) {
764 /*
765 * Save directory entry's inode number and
766 * reclen in ndp->ni_ufs area, and release
767 * directory buffer.
768 */
769 *foundp = 1;
770 return (0);
771 }
772 }
773 *prevoffp = *offp;
774 *offp += ep->e2d_reclen;
775 offset += ep->e2d_reclen;
776 *entryoffsetinblockp = offset;
777 if (ep->e2d_ino)
778 *endusefulp = *offp;
779 /*
780 * Get pointer to the next entry.
781 */
782 ep = (struct ext2fs_direct_2 *)((char *)data + offset);
783 }
784
785 return (0);
786}
787
717void
718ext2_dirbad(struct inode *ip, doff_t offset, char *how)
719{
720 struct mount *mp;
721
722 mp = ITOV(ip)->v_mount;
723 if ((mp->mnt_flag & MNT_RDONLY) == 0)
724 panic("ext2_dirbad: %s: bad dir ino %lu at offset %ld: %s\n",

--- 51 unchanged lines hidden (view full) ---

776 * directory entry will refer to. Dvp is a pointer to the directory to
777 * be written, which was left locked by namei. Remaining parameters
778 * (dp->i_offset, dp->i_count) indicate how the space for the new
779 * entry is to be obtained.
780 */
781int
782ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp)
783{
788void
789ext2_dirbad(struct inode *ip, doff_t offset, char *how)
790{
791 struct mount *mp;
792
793 mp = ITOV(ip)->v_mount;
794 if ((mp->mnt_flag & MNT_RDONLY) == 0)
795 panic("ext2_dirbad: %s: bad dir ino %lu at offset %ld: %s\n",

--- 51 unchanged lines hidden (view full) ---

847 * directory entry will refer to. Dvp is a pointer to the directory to
848 * be written, which was left locked by namei. Remaining parameters
849 * (dp->i_offset, dp->i_count) indicate how the space for the new
850 * entry is to be obtained.
851 */
852int
853ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp)
854{
784 struct ext2fs_direct_2 *ep, *nep;
785 struct inode *dp;
855 struct inode *dp;
786 struct buf *bp;
787 struct ext2fs_direct_2 newdir;
788 struct iovec aiov;
789 struct uio auio;
856 struct ext2fs_direct_2 newdir;
857 struct iovec aiov;
858 struct uio auio;
790 u_int dsize;
791 int error, loc, newentrysize, spacefree;
792 char *dirbuf;
793 int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize;
859 int error, newentrysize;
860 int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize;
794
795
796#ifdef INVARIANTS
797 if ((cnp->cn_flags & SAVENAME) == 0)
798 panic("ext2_direnter: missing name");
799#endif
800 dp = VTOI(dvp);
801 newdir.e2d_ino = ip->i_number;
802 newdir.e2d_namlen = cnp->cn_namelen;
803 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
804 EXT2F_INCOMPAT_FTYPE))
805 newdir.e2d_type = DTTOFT(IFTODT(ip->i_mode));
806 else
807 newdir.e2d_type = EXT2_FT_UNKNOWN;
808 bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
809 newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen);
861
862
863#ifdef INVARIANTS
864 if ((cnp->cn_flags & SAVENAME) == 0)
865 panic("ext2_direnter: missing name");
866#endif
867 dp = VTOI(dvp);
868 newdir.e2d_ino = ip->i_number;
869 newdir.e2d_namlen = cnp->cn_namelen;
870 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
871 EXT2F_INCOMPAT_FTYPE))
872 newdir.e2d_type = DTTOFT(IFTODT(ip->i_mode));
873 else
874 newdir.e2d_type = EXT2_FT_UNKNOWN;
875 bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
876 newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen);
877
878 if (ext2_htree_has_idx(dp)) {
879 error = ext2_htree_add_entry(dvp, &newdir, cnp);
880 if (error) {
881 dp->i_flags &= ~EXT4_INDEX;
882 dp->i_flags |= IN_CHANGE | IN_UPDATE;
883 }
884 return (error);
885 }
886
887 if (EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX) &&
888 !ext2_htree_has_idx(dp)) {
889 if ((dp->i_size / DIRBLKSIZ) == 1 &&
890 dp->i_offset == DIRBLKSIZ) {
891 /*
892 * Making indexed directory when one block is not
893 * enough to save all entries.
894 */
895 return ext2_htree_create_index(dvp, cnp, &newdir);
896 }
897 }
898
810 if (dp->i_count == 0) {
811 /*
812 * If dp->i_count is 0, then namei could find no
813 * space in the directory. Here, dp->i_offset will
814 * be on a directory block boundary and we will write the
815 * new entry into a fresh block.
816 */
817 if (dp->i_offset & (DIRBLKSIZ - 1))

--- 15 unchanged lines hidden (view full) ---

833 panic("ext2_direnter: frag size");
834 else if (!error) {
835 dp->i_size = roundup2(dp->i_size, DIRBLKSIZ);
836 dp->i_flag |= IN_CHANGE;
837 }
838 return (error);
839 }
840
899 if (dp->i_count == 0) {
900 /*
901 * If dp->i_count is 0, then namei could find no
902 * space in the directory. Here, dp->i_offset will
903 * be on a directory block boundary and we will write the
904 * new entry into a fresh block.
905 */
906 if (dp->i_offset & (DIRBLKSIZ - 1))

--- 15 unchanged lines hidden (view full) ---

922 panic("ext2_direnter: frag size");
923 else if (!error) {
924 dp->i_size = roundup2(dp->i_size, DIRBLKSIZ);
925 dp->i_flag |= IN_CHANGE;
926 }
927 return (error);
928 }
929
930 error = ext2_add_entry(dvp, &newdir);
931 if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
932 error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
933 cnp->cn_cred, cnp->cn_thread);
934 return (error);
935}
936
937/*
938 * Insert an entry into the directory block.
939 * Compact the contents.
940 */
941int
942ext2_add_entry(struct vnode *dvp, struct ext2fs_direct_2 *entry)
943{
944 struct ext2fs_direct_2 *ep, *nep;
945 struct inode *dp;
946 struct buf *bp;
947 u_int dsize;
948 int error, loc, newentrysize, spacefree;
949 char *dirbuf;
950
951 dp = VTOI(dvp);
952
841 /*
842 * If dp->i_count is non-zero, then namei found space
843 * for the new entry in the range dp->i_offset to
844 * dp->i_offset + dp->i_count in the directory.
845 * To use this space, we may have to compact the entries located
846 * there, by copying them together towards the beginning of the
847 * block, leaving the free space in one usable chunk at the end.
848 */

--- 15 unchanged lines hidden (view full) ---

864 return (error);
865 /*
866 * Find space for the new entry. In the simple case, the entry at
867 * offset base will have the space. If it does not, then namei
868 * arranged that compacting the region dp->i_offset to
869 * dp->i_offset + dp->i_count would yield the
870 * space.
871 */
953 /*
954 * If dp->i_count is non-zero, then namei found space
955 * for the new entry in the range dp->i_offset to
956 * dp->i_offset + dp->i_count in the directory.
957 * To use this space, we may have to compact the entries located
958 * there, by copying them together towards the beginning of the
959 * block, leaving the free space in one usable chunk at the end.
960 */

--- 15 unchanged lines hidden (view full) ---

976 return (error);
977 /*
978 * Find space for the new entry. In the simple case, the entry at
979 * offset base will have the space. If it does not, then namei
980 * arranged that compacting the region dp->i_offset to
981 * dp->i_offset + dp->i_count would yield the
982 * space.
983 */
984 newentrysize = EXT2_DIR_REC_LEN(entry->e2d_namlen);
872 ep = (struct ext2fs_direct_2 *)dirbuf;
873 dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen);
874 spacefree = ep->e2d_reclen - dsize;
875 for (loc = ep->e2d_reclen; loc < dp->i_count; ) {
876 nep = (struct ext2fs_direct_2 *)(dirbuf + loc);
877 if (ep->e2d_ino) {
878 /* trim the existing slot */
879 ep->e2d_reclen = dsize;

--- 9 unchanged lines hidden (view full) ---

889 }
890 /*
891 * Update the pointer fields in the previous entry (if any),
892 * copy in the new entry, and write out the block.
893 */
894 if (ep->e2d_ino == 0) {
895 if (spacefree + dsize < newentrysize)
896 panic("ext2_direnter: compact1");
985 ep = (struct ext2fs_direct_2 *)dirbuf;
986 dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen);
987 spacefree = ep->e2d_reclen - dsize;
988 for (loc = ep->e2d_reclen; loc < dp->i_count; ) {
989 nep = (struct ext2fs_direct_2 *)(dirbuf + loc);
990 if (ep->e2d_ino) {
991 /* trim the existing slot */
992 ep->e2d_reclen = dsize;

--- 9 unchanged lines hidden (view full) ---

1002 }
1003 /*
1004 * Update the pointer fields in the previous entry (if any),
1005 * copy in the new entry, and write out the block.
1006 */
1007 if (ep->e2d_ino == 0) {
1008 if (spacefree + dsize < newentrysize)
1009 panic("ext2_direnter: compact1");
897 newdir.e2d_reclen = spacefree + dsize;
1010 entry->e2d_reclen = spacefree + dsize;
898 } else {
899 if (spacefree < newentrysize)
900 panic("ext2_direnter: compact2");
1011 } else {
1012 if (spacefree < newentrysize)
1013 panic("ext2_direnter: compact2");
901 newdir.e2d_reclen = spacefree;
1014 entry->e2d_reclen = spacefree;
902 ep->e2d_reclen = dsize;
903 ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
904 }
1015 ep->e2d_reclen = dsize;
1016 ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
1017 }
905 bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize);
1018 bcopy((caddr_t)entry, (caddr_t)ep, (u_int)newentrysize);
906 if (DOINGASYNC(dvp)) {
907 bdwrite(bp);
908 error = 0;
909 } else {
910 error = bwrite(bp);
911 }
912 dp->i_flag |= IN_CHANGE | IN_UPDATE;
1019 if (DOINGASYNC(dvp)) {
1020 bdwrite(bp);
1021 error = 0;
1022 } else {
1023 error = bwrite(bp);
1024 }
1025 dp->i_flag |= IN_CHANGE | IN_UPDATE;
913 if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
914 error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
915 cnp->cn_cred, cnp->cn_thread);
916 return (error);
917}
918
919/*
920 * Remove a directory entry after a call to namei, using
921 * the parameters which it left in nameidata. The entry
922 * dp->i_offset contains the offset into the directory of the
923 * entry to be eliminated. The dp->i_count field contains the

--- 193 unchanged lines hidden ---
1026 return (error);
1027}
1028
1029/*
1030 * Remove a directory entry after a call to namei, using
1031 * the parameters which it left in nameidata. The entry
1032 * dp->i_offset contains the offset into the directory of the
1033 * entry to be eliminated. The dp->i_count field contains the

--- 193 unchanged lines hidden ---