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 --- |