msdosfs_lookup.c (203827) | msdosfs_lookup.c (204474) |
---|---|
1/* $FreeBSD: head/sys/fs/msdosfs/msdosfs_lookup.c 203827 2010-02-13 12:41:07Z kib $ */ | 1/* $FreeBSD: head/sys/fs/msdosfs/msdosfs_lookup.c 204474 2010-02-28 17:17:29Z kib $ */ |
2/* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ 3 4/*- 5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 7 * All rights reserved. 8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 9 * --- 46 unchanged lines hidden (view full) --- 56#include <sys/vnode.h> 57 58#include <fs/msdosfs/bpb.h> 59#include <fs/msdosfs/direntry.h> 60#include <fs/msdosfs/denode.h> 61#include <fs/msdosfs/fat.h> 62#include <fs/msdosfs/msdosfsmount.h> 63 | 2/* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ 3 4/*- 5 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 6 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 7 * All rights reserved. 8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 9 * --- 46 unchanged lines hidden (view full) --- 56#include <sys/vnode.h> 57 58#include <fs/msdosfs/bpb.h> 59#include <fs/msdosfs/direntry.h> 60#include <fs/msdosfs/denode.h> 61#include <fs/msdosfs/fat.h> 62#include <fs/msdosfs/msdosfsmount.h> 63 |
64static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, 65 struct componentname *cnp, u_int64_t *inum); 66static int msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff, 67 struct vnode **rvp); 68 69int 70msdosfs_lookup(struct vop_cachedlookup_args *ap) 71{ 72 73 return (msdosfs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); 74} 75 |
|
64/* 65 * When we search a directory the blocks containing directory entries are 66 * read and examined. The directory entries contain information that would 67 * normally be in the inode of a unix filesystem. This means that some of 68 * a directory's contents may also be in memory resident denodes (sort of 69 * an inode). This can cause problems if we are searching while some other 70 * process is modifying a directory. To prevent one process from accessing 71 * incompletely modified directory information we depend upon being the 72 * sole owner of a directory block. bread/brelse provide this service. 73 * This being the case, when a process modifies a directory it must first 74 * acquire the disk block that contains the directory entry to be modified. 75 * Then update the disk block and the denode, and then write the disk block 76 * out to disk. This way disk blocks containing directory entries and in 77 * memory denode's will be in synch. 78 */ | 76/* 77 * When we search a directory the blocks containing directory entries are 78 * read and examined. The directory entries contain information that would 79 * normally be in the inode of a unix filesystem. This means that some of 80 * a directory's contents may also be in memory resident denodes (sort of 81 * an inode). This can cause problems if we are searching while some other 82 * process is modifying a directory. To prevent one process from accessing 83 * incompletely modified directory information we depend upon being the 84 * sole owner of a directory block. bread/brelse provide this service. 85 * This being the case, when a process modifies a directory it must first 86 * acquire the disk block that contains the directory entry to be modified. 87 * Then update the disk block and the denode, and then write the disk block 88 * out to disk. This way disk blocks containing directory entries and in 89 * memory denode's will be in synch. 90 */ |
79int 80msdosfs_lookup(ap) 81 struct vop_cachedlookup_args /* { 82 struct vnode *a_dvp; 83 struct vnode **a_vpp; 84 struct componentname *a_cnp; 85 } */ *ap; | 91static int 92msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, 93 struct componentname *cnp, u_int64_t *dd_inum) |
86{ 87 struct mbnambuf nb; | 94{ 95 struct mbnambuf nb; |
88 struct vnode *vdp = ap->a_dvp; 89 struct vnode **vpp = ap->a_vpp; 90 struct componentname *cnp = ap->a_cnp; | |
91 daddr_t bn; 92 int error; 93 int slotcount; 94 int slotoffset = 0; 95 int frcn; 96 u_long cluster; 97 int blkoff; 98 int diroff; --- 5 unchanged lines hidden (view full) --- 104 struct denode *tdp; 105 struct msdosfsmount *pmp; 106 struct buf *bp = 0; 107 struct direntry *dep = NULL; 108 u_char dosfilename[12]; 109 int flags = cnp->cn_flags; 110 int nameiop = cnp->cn_nameiop; 111 int unlen; | 96 daddr_t bn; 97 int error; 98 int slotcount; 99 int slotoffset = 0; 100 int frcn; 101 u_long cluster; 102 int blkoff; 103 int diroff; --- 5 unchanged lines hidden (view full) --- 109 struct denode *tdp; 110 struct msdosfsmount *pmp; 111 struct buf *bp = 0; 112 struct direntry *dep = NULL; 113 u_char dosfilename[12]; 114 int flags = cnp->cn_flags; 115 int nameiop = cnp->cn_nameiop; 116 int unlen; |
117 u_int64_t inode1; |
|
112 113 int wincnt = 1; 114 int chksum = -1, chksum_ok; 115 int olddos = 1; 116 117#ifdef MSDOSFS_DEBUG 118 printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr); 119#endif 120 dp = VTODE(vdp); 121 pmp = dp->de_pmp; | 118 119 int wincnt = 1; 120 int chksum = -1, chksum_ok; 121 int olddos = 1; 122 123#ifdef MSDOSFS_DEBUG 124 printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr); 125#endif 126 dp = VTODE(vdp); 127 pmp = dp->de_pmp; |
122 *vpp = NULL; | 128 if (vpp != NULL) 129 *vpp = NULL; |
123#ifdef MSDOSFS_DEBUG 124 printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", 125 vdp, dp, dp->de_Attributes); 126#endif 127 | 130#ifdef MSDOSFS_DEBUG 131 printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", 132 vdp, dp, dp->de_Attributes); 133#endif 134 |
135 restart: |
|
128 /* 129 * If they are going after the . or .. entry in the root directory, 130 * they won't find it. DOS filesystems don't have them in the root 131 * directory. So, we fake it. deget() is in on this scam too. 132 */ 133 if ((vdp->v_vflag & VV_ROOT) && cnp->cn_nameptr[0] == '.' && 134 (cnp->cn_namelen == 1 || 135 (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) { --- 295 unchanged lines hidden (view full) --- 431 /* 432 * If we entered at foundroot, then we are looking for the . or .. 433 * entry of the filesystems root directory. isadir and scn were 434 * setup before jumping here. And, bp is already null. 435 */ 436 if (FAT32(pmp) && scn == MSDOSFSROOT) 437 scn = pmp->pm_rootdirblk; 438 | 136 /* 137 * If they are going after the . or .. entry in the root directory, 138 * they won't find it. DOS filesystems don't have them in the root 139 * directory. So, we fake it. deget() is in on this scam too. 140 */ 141 if ((vdp->v_vflag & VV_ROOT) && cnp->cn_nameptr[0] == '.' && 142 (cnp->cn_namelen == 1 || 143 (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) { --- 295 unchanged lines hidden (view full) --- 439 /* 440 * If we entered at foundroot, then we are looking for the . or .. 441 * entry of the filesystems root directory. isadir and scn were 442 * setup before jumping here. And, bp is already null. 443 */ 444 if (FAT32(pmp) && scn == MSDOSFSROOT) 445 scn = pmp->pm_rootdirblk; 446 |
447 if (dd_inum != NULL) { 448 *dd_inum = (uint64_t)pmp->pm_bpcluster * scn + blkoff; 449 return (0); 450 } 451 |
|
439 /* 440 * If deleting, and at end of pathname, return 441 * parameters which can be used to remove file. 442 */ 443 if (nameiop == DELETE && (flags & ISLASTCN)) { 444 /* 445 * Don't allow deleting the root. 446 */ --- 56 unchanged lines hidden (view full) --- 503 * directory because we may need it again if a symbolic link 504 * is relative to the current directory. Instead we save it 505 * unlocked as "pdp". We must get the target inode before unlocking 506 * the directory to insure that the inode will not be removed 507 * before we get it. We prevent deadlock by always fetching 508 * inodes from the root, moving down the directory tree. Thus 509 * when following backward pointers ".." we must unlock the 510 * parent directory before getting the requested directory. | 452 /* 453 * If deleting, and at end of pathname, return 454 * parameters which can be used to remove file. 455 */ 456 if (nameiop == DELETE && (flags & ISLASTCN)) { 457 /* 458 * Don't allow deleting the root. 459 */ --- 56 unchanged lines hidden (view full) --- 516 * directory because we may need it again if a symbolic link 517 * is relative to the current directory. Instead we save it 518 * unlocked as "pdp". We must get the target inode before unlocking 519 * the directory to insure that the inode will not be removed 520 * before we get it. We prevent deadlock by always fetching 521 * inodes from the root, moving down the directory tree. Thus 522 * when following backward pointers ".." we must unlock the 523 * parent directory before getting the requested directory. |
511 * There is a potential race condition here if both the current 512 * and parent directories are removed before the VFS_VGET for the 513 * inode associated with ".." returns. We hope that this occurs 514 * infrequently since we cannot avoid this race condition without 515 * implementing a sophisticated deadlock detection algorithm. 516 * Note also that this simple deadlock detection scheme will not 517 * work if the filesystem has any hard links other than ".." 518 * that point backwards in the directory structure. | |
519 */ 520 pdp = vdp; 521 if (flags & ISDOTDOT) { | 524 */ 525 pdp = vdp; 526 if (flags & ISDOTDOT) { |
522 VOP_UNLOCK(pdp, 0); 523 error = deget(pmp, cluster, blkoff, &tdp); 524 vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); | 527 error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp); |
525 if (error) 526 return (error); | 528 if (error) 529 return (error); |
527 *vpp = DETOV(tdp); | 530 /* 531 * Recheck that ".." still points to the inode we 532 * looked up before pdp lock was dropped. 533 */ 534 error = msdosfs_lookup_(pdp, NULL, cnp, &inode1); 535 if (error) { 536 vput(*vpp); 537 return (error); 538 } 539 if (VTODE(*vpp)->de_inode != inode1) { 540 vput(*vpp); 541 goto restart; 542 } |
528 } else if (dp->de_StartCluster == scn && isadir) { 529 VREF(vdp); /* we want ourself, ie "." */ 530 *vpp = vdp; 531 } else { 532 if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) 533 return (error); 534 *vpp = DETOV(tdp); 535 } 536 537 /* 538 * Insert name into cache if appropriate. 539 */ 540 if (cnp->cn_flags & MAKEENTRY) 541 cache_enter(vdp, *vpp, cnp); 542 return (0); 543} 544 | 543 } else if (dp->de_StartCluster == scn && isadir) { 544 VREF(vdp); /* we want ourself, ie "." */ 545 *vpp = vdp; 546 } else { 547 if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) 548 return (error); 549 *vpp = DETOV(tdp); 550 } 551 552 /* 553 * Insert name into cache if appropriate. 554 */ 555 if (cnp->cn_flags & MAKEENTRY) 556 cache_enter(vdp, *vpp, cnp); 557 return (0); 558} 559 |
560static int 561msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff, 562 struct vnode **rvp) 563{ 564 struct mount *mp; 565 struct msdosfsmount *pmp; 566 struct denode *rdp; 567 int ltype, error; 568 569 mp = vp->v_mount; 570 pmp = VFSTOMSDOSFS(mp); 571 ltype = VOP_ISLOCKED(vp); 572 KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED, 573 ("msdosfs_deget_dotdot: vp not locked")); 574 575 error = vfs_busy(mp, MBF_NOWAIT); 576 if (error != 0) { 577 vfs_ref(mp); 578 VOP_UNLOCK(vp, 0); 579 error = vfs_busy(mp, 0); 580 vn_lock(vp, ltype | LK_RETRY); 581 vfs_rel(mp); 582 if (error != 0) 583 return (ENOENT); 584 if (vp->v_iflag & VI_DOOMED) { 585 vfs_unbusy(mp); 586 return (ENOENT); 587 } 588 } 589 VOP_UNLOCK(vp, 0); 590 error = deget(pmp, cluster, blkoff, &rdp); 591 vfs_unbusy(mp); 592 if (error == 0) 593 *rvp = DETOV(rdp); 594 vn_lock(vp, ltype | LK_RETRY); 595 if (vp->v_iflag & VI_DOOMED) { 596 if (error == 0) 597 vput(*rvp); 598 error = ENOENT; 599 } 600 return (error); 601} 602 |
|
545/* 546 * dep - directory entry to copy into the directory 547 * ddep - directory to add to 548 * depp - return the address of the denode for the created directory entry 549 * if depp != 0 550 * cnp - componentname needed for Win95 long filenames 551 */ 552int --- 535 unchanged lines hidden --- | 603/* 604 * dep - directory entry to copy into the directory 605 * ddep - directory to add to 606 * depp - return the address of the denode for the created directory entry 607 * if depp != 0 608 * cnp - componentname needed for Win95 long filenames 609 */ 610int --- 535 unchanged lines hidden --- |