finish updating to new vnode interface, from ws.

This commit is contained in:
cgd 1994-07-18 21:38:08 +00:00
parent fc5405fc33
commit fb6819f643
9 changed files with 1035 additions and 443 deletions

View File

@ -1,5 +1,35 @@
/* $NetBSD: denode.h,v 1.5 1994/07/16 21:33:17 cgd Exp $ */
/* $NetBSD: denode.h,v 1.6 1994/07/18 21:38:08 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -132,14 +162,10 @@ struct denode {
/*
* Values for the de_flag field of the denode.
*/
#define DELOCKED 0x0001 /* directory entry is locked */
#define DEWANT 0x0002 /* someone wants this de */
#define DERENAME 0x0004 /* de is being renamed */
#define DEUPD 0x0008 /* file has been modified */
#define DESHLOCK 0x0010 /* file has shared lock */
#define DEEXLOCK 0x0020 /* file has exclusive lock */
#define DELWAIT 0x0040 /* someone waiting on file lock */
#define DEMOD 0x0080 /* denode wants to be written back to disk */
#define DE_LOCKED 0x0001 /* directory entry is locked */
#define DE_WANT 0x0002 /* someone wants this de */
#define DE_UPD 0x0004 /* file has been modified */
#define DE_MOD 0x0080 /* denode wants to be written back to disk */
/*
* Transfer directory entries between internal and external form.
@ -165,23 +191,20 @@ struct denode {
#define de_forw de_chain[0]
#define de_back de_chain[1]
#if defined(KERNEL)
#ifdef KERNEL
#define VTODE(vp) ((struct denode *)(vp)->v_data)
#define DETOV(de) ((de)->de_vnode)
#define DELOCK(de) delock(de)
#define DEUNLOCK(de) deunlock(de)
#define DEUPDAT(dep, t, waitfor) \
if (dep->de_flag & DEUPD) \
#define DE_UPDAT(dep, t, waitfor) \
if (dep->de_flag & DE_UPD) \
(void) deupdat(dep, t, waitfor);
#define DETIMES(dep, t) \
if (dep->de_flag & DEUPD) { \
(dep)->de_flag |= DEMOD; \
#define DE_TIMES(dep, t) \
if (dep->de_flag & DE_UPD) { \
(dep)->de_flag |= DE_MOD; \
unix2dostime(t, &dep->de_Date, &dep->de_Time); \
(dep)->de_flag &= ~DEUPD; \
(dep)->de_flag &= ~DE_UPD; \
}
/*
@ -239,11 +262,4 @@ int msdosfs_reallocblks __P((struct vop_reallocblks_args *));
* Internal service routine prototypes.
*/
int deget __P((struct msdosfsmount * pmp, u_long dirclust, u_long diroffset, struct direntry * direntptr, struct denode ** depp));
static void deput __P((struct denode *dep));
static __inline void deput(dep)
struct denode *dep;
{
vput(DETOV(dep));
}
#endif /* defined(KERNEL) */
#endif /* KERNEL */

View File

@ -1,5 +1,35 @@
/* $NetBSD: direntry.h,v 1.5 1994/07/16 21:33:19 cgd Exp $ */
/* $NetBSD: direntry.h,v 1.6 1994/07/18 21:38:10 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -64,9 +94,9 @@ struct direntry {
#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
#define DD_YEAR_SHIFT 9
#if defined(KERNEL)
#ifdef KERNEL
void unix2dostime __P((struct timespec * tsp, u_short * ddp, u_short * dtp));
void dos2unixtime __P((u_short dd, u_short dt, struct timespec * tsp));
int dos2unixfn __P((u_char dn[11], u_char * un));
void unix2dosfn __P((u_char * un, u_char dn[11], int unlen));
#endif /* defined(KERNEL) */
#endif /* KERNEL */

View File

@ -1,5 +1,35 @@
/* $NetBSD: fat.h,v 1.2 1994/06/29 06:35:33 cgd Exp $ */
/* $NetBSD: fat.h,v 1.3 1994/07/18 21:38:11 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -42,6 +72,7 @@
#define MSDOSFSEOF(cn) (((cn) & 0xfff8) == 0xfff8)
#ifdef KERNEL
/*
* These are the values for the function argument to the function
* fatentry().
@ -50,10 +81,15 @@
#define FAT_SET 0x0002 /* set a fat entry */
#define FAT_GET_AND_SET (FAT_GET | FAT_SET)
#if defined(KERNEL)
int pcbmap __P((struct denode * dep, u_long findcn, daddr_t * bnp, u_long * cnp));
int clusterfree __P((struct msdosfsmount * pmp, u_long cn, u_long * oldcnp));
int clusteralloc __P((struct msdosfsmount * pmp, u_long * retcluster, u_long fillwith));
int fatentry __P((int function, struct msdosfsmount * pmp, u_long cluster, u_long * oldcontents, u_long newcontents));
int freeclusterchain __P((struct msdosfsmount * pmp, u_long startchain));
#endif /* defined(KERNEL) */
/*
* Flags to extendfile:
*/
#define DE_CLEAR 1 /* Zero out the blocks allocated */
int pcbmap __P((struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp));
int clusterfree __P((struct msdosfsmount *pmp, u_long cn, u_long *oldcnp));
int clusteralloc __P((struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith, u_long *retcluster, u_long *got));
int fatentry __P((int function, struct msdosfsmount *pmp, u_long cluster, u_long *oldcontents, u_long newcontents));
int freeclusterchain __P((struct msdosfsmount *pmp, u_long startchain));
int extendfile __P((struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags));
#endif /* KERNEL */

View File

@ -1,14 +1,44 @@
/* $NetBSD: msdosfs_denode.c,v 1.6 1994/07/16 21:33:20 cgd Exp $ */
/* $NetBSD: msdosfs_denode.c,v 1.7 1994/07/18 21:38:12 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
* You can do anything you want with this software, just don't say you wrote
* it, and don't reoove this notice.
* it, and don't remove this notice.
*
* This software is provided "as is".
*
* The authop supplies this software to be publicly redistributed on the
* The author supplies this software to be publicly redistributed on the
* understanding that the author is not responsible for the correct
* functioning of this software in any circumstances and is not liable for
* any damages caused by this software.
@ -58,8 +88,8 @@ msdosfs_hashget(dev, dirclust, diroff)
|| dev != dep->de_dev
|| dep->de_refcnt == 0)
continue;
if (dep->de_flag & DELOCKED) {
dep->de_flag |= DEWANT;
if (dep->de_flag & DE_LOCKED) {
dep->de_flag |= DE_WANT;
sleep((caddr_t)dep, PINOD);
break;
}
@ -82,13 +112,13 @@ msdosfs_hashins(dep)
dep->de_next = deq;
dep->de_prev = depp;
*depp = dep;
if (dep->de_flag & DELOCKED)
if (dep->de_flag & DE_LOCKED)
panic("msdosfs_hashins: already locked");
if (curproc)
dep->de_lockholder = curproc->p_pid;
else
dep->de_lockholder = -1;
dep->de_flag |= DELOCKED;
dep->de_flag |= DE_LOCKED;
}
static void
@ -135,10 +165,10 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
struct vnode *nvp;
struct buf *bp;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("deget(pmp %08x, dirclust %d, diroffset %x, direntptr %x, depp %08x)\n",
pmp, dirclust, diroffset, direntptr, depp);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* If dir entry is given and refers to a directory, convert to
@ -284,9 +314,9 @@ deupdat(dep, tp, waitfor)
struct timespec ts;
struct vnode *vp = DETOV(dep);
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("deupdat(): dep %08x\n", dep);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* If the update bit is off, or this denode is from a readonly
@ -295,7 +325,7 @@ deupdat(dep, tp, waitfor)
* directory entries that describe a directory do not ever get
* updated. This is the way dos treats them.
*/
if ((dep->de_flag & DEUPD) == 0 ||
if ((dep->de_flag & DE_UPD) == 0 ||
vp->v_mount->mnt_flag & MNT_RDONLY ||
dep->de_Attributes & ATTR_DIRECTORY ||
dep->de_refcnt <= 0)
@ -313,7 +343,7 @@ deupdat(dep, tp, waitfor)
*/
TIMEVAL_TO_TIMESPEC(&time, &ts);
unix2dostime(&ts, &dep->de_Date, &dep->de_Time);
dep->de_flag &= ~DEUPD;
dep->de_flag &= ~DE_UPD;
/*
* Copy the directory entry out of the denode into the cluster it
@ -356,9 +386,9 @@ detrunc(dep, length, flags, cred, p)
struct buf *bp;
struct msdosfsmount *pmp = dep->de_pmp;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("detrunc(): file %s, length %d, flags %d\n", dep->de_Name, length, flags);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* Disallow attempts to truncate the root directory since it is of
@ -376,14 +406,8 @@ detrunc(dep, length, flags, cred, p)
vnode_pager_setsize(DETOV(dep), length);
if (dep->de_FileSize <= length) {
dep->de_flag |= DEUPD;
error = deupdat(dep, &time, 1);
#if defined(MSDOSFSDEBUG)
printf("detrunc(): file is shorter return point, errno %d\n", error);
#endif /* defined(MSDOSFSDEBUG) */
return error;
}
if (dep->de_FileSize < length)
return deextend(dep, length, cred);
/*
* If the desired length is 0 then remember the starting cluster of
@ -399,12 +423,10 @@ detrunc(dep, length, flags, cred, p)
dep->de_StartCluster = 0;
eofentry = ~0;
} else {
error = pcbmap(dep, (length - 1) >> pmp->pm_cnshift,
0, &eofentry);
if (error) {
#if defined(MSDOSFSDEBUG)
if (error = pcbmap(dep, de_clcount(pmp, length) - 1, 0, &eofentry)) {
#ifdef MSDOSFS_DEBUG
printf("detrunc(): pcbmap fails %d\n", error);
#endif /* defined(MSDOSFSDEBUG) */
#endif
return error;
}
}
@ -426,14 +448,14 @@ detrunc(dep, length, flags, cred, p)
error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster,
NOCRED, &bp);
} else {
bn = (length - 1) >> pmp->pm_cnshift;
bn = de_blk(pmp, length);
error = bread(DETOV(dep), bn, pmp->pm_bpcluster,
NOCRED, &bp);
}
if (error) {
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("detrunc(): bread fails %d\n", error);
#endif /* defined(MSDOSFSDEBUG) */
#endif
return error;
}
vnode_pager_uncache(DETOV(dep)); /* what's this for? */
@ -452,14 +474,14 @@ detrunc(dep, length, flags, cred, p)
* we free the trailing clusters.
*/
dep->de_FileSize = length;
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
vflags = (length > 0 ? V_SAVE : 0) | V_SAVEMETA;
vinvalbuf(DETOV(dep), vflags, cred, p, 0, 0);
allerror = deupdat(dep, &time, MNT_WAIT);
#if defined(MSDOSFSDEBUG)
allerror = deupdat(dep, &time, 1);
#ifdef MSDOSFS_DEBUG
printf("detrunc(): allerror %d, eofentry %d\n",
allerror, eofentry);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* If we need to break the cluster chain for the file then do it
@ -469,9 +491,9 @@ detrunc(dep, length, flags, cred, p)
error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
&chaintofree, CLUST_EOFE);
if (error) {
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("detrunc(): fatentry errors %d\n", error);
#endif /* defined(MSDOSFSDEBUG) */
#endif
return error;
}
fc_setcache(dep, FC_LASTFC, (length - 1) >> pmp->pm_cnshift,
@ -498,9 +520,8 @@ deextend(dep, length, cred)
struct ucred *cred;
{
struct msdosfsmount *pmp = dep->de_pmp;
off_t foff;
u_long count;
int error;
struct buf *bp;
/*
* The root of a DOS filesystem cannot be extended.
@ -521,20 +542,22 @@ deextend(dep, length, cred)
panic("deextend: file too large");
/*
* Compute the offset of the first byte after the last block in the
* file.
* Compute the number of clusters to allocate.
*/
foff = (dep->de_FileSize + (pmp->pm_bpcluster - 1)) & ~pmp->pm_crbomask;
while (foff < length) {
if (error = extendfile(dep, &bp, 0))
count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
if (count > 0) {
if (count > pmp->pm_freeclustercount)
return ENOSPC;
if (error = extendfile(dep, count, NULL, NULL, DE_CLEAR)) {
/* truncate the added clusters away again */
(void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
return error;
dep->de_flag |= DEUPD;
bdwrite(bp);
foff += pmp->pm_bpcluster;
dep->de_FileSize += pmp->pm_bpcluster;
}
}
dep->de_flag |= DE_UPD;
dep->de_FileSize = length;
return deupdat(dep, &time);
return deupdat(dep, &time, 1);
}
/*
@ -544,7 +567,6 @@ deextend(dep, length, cred)
reinsert(dep)
struct denode *dep;
{
struct msdosfsmount *pmp = dep->de_pmp;
union dehead *deh;
/*
@ -572,10 +594,10 @@ msdosfs_reclaim(ap)
int i;
extern int prtactive;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_reclaim(): dep %08x, file %s, refcnt %d\n",
dep, dep->de_Name, dep->de_refcnt);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (prtactive && vp->v_usecount != 0)
vprint("msdosfs_reclaim(): pushing active", vp);
@ -613,9 +635,9 @@ msdosfs_inactive(ap)
int error = 0;
extern int prtactive;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_inactive(): dep %08x, de_Name[0] %x\n", dep, dep->de_Name[0]);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (prtactive && vp->v_usecount != 0)
vprint("msdosfs_inactive(): pushing active", vp);
@ -635,63 +657,29 @@ msdosfs_inactive(ap)
* filesystem, then truncate the file, and mark the directory slot
* as empty. (This may not be necessary for the dos filesystem.)
*/
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_inactive(): dep %08x, refcnt %d, mntflag %x, MNT_RDONLY %x\n",
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
#endif /* defined(MSDOSFSDEBUG) */
DELOCK(dep);
#endif
VOP_LOCK(vp);
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
dep->de_Name[0] = SLOT_DELETED;
}
DEUPDAT(dep, &time, 0);
DEUNLOCK(dep);
DE_UPDAT(dep, &time, 0);
VOP_UNLOCK(vp);
dep->de_flag = 0;
/*
* If we are done with the denode, then reclaim it so that it can
* be reused now.
*/
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
dep->de_Name[0]);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (vp->v_usecount == 0 && dep->de_Name[0] == SLOT_DELETED)
vgone(vp);
return error;
}
int
delock(dep)
struct denode *dep;
{
while (dep->de_flag & DELOCKED) {
dep->de_flag |= DEWANT;
if (dep->de_lockholder == curproc->p_pid)
panic("delock: locking against myself");
dep->de_lockwaiter = curproc->p_pid;
(void) sleep((caddr_t) dep, PINOD);
}
dep->de_lockwaiter = 0;
dep->de_lockholder = curproc->p_pid;
dep->de_flag |= DELOCKED;
return 0;
}
int
deunlock(dep)
struct denode *dep;
{
if ((dep->de_flag & DELOCKED) == 0)
vprint("deunlock: found unlocked denode", DETOV(dep));
dep->de_lockholder = 0;
dep->de_flag &= ~DELOCKED;
if (dep->de_flag & DEWANT) {
dep->de_flag &= ~DEWANT;
wakeup((caddr_t) dep);
}
return 0;
}

View File

@ -1,5 +1,35 @@
/* $NetBSD: msdosfs_fat.c,v 1.7 1994/07/16 21:33:21 cgd Exp $ */
/* $NetBSD: msdosfs_fat.c,v 1.8 1994/07/18 21:38:14 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -53,7 +83,6 @@ int fc_largedistance; /* off by more than LMMAX */
/* Byte offset in FAT on filesystem pmp, cluster cn */
#define FATOFS(pmp, cn) (FAT12(pmp) ? (cn) * 3 / 2 : (cn) * 2)
static void
fatblock(pmp, ofs, bnp, sizep, bop)
struct msdosfsmount *pmp;
@ -261,15 +290,14 @@ fc_purge(dep, frcn)
}
/*
* Once the first fat is updated the other copies of the fat must also be
* updated. This function does this.
* Update all copies of the fat. The first copy is updated last.
*
* pmp - msdosfsmount structure for filesystem to update
* bp - addr of modified fat block
* fatbn - block number relative to begin of filesystem of the modified fat block.
*/
void
updateotherfats(pmp, bp, fatbn)
updatefats(pmp, bp, fatbn)
struct msdosfsmount *pmp;
struct buf *bp;
u_long fatbn;
@ -277,10 +305,10 @@ updateotherfats(pmp, bp, fatbn)
int i;
struct buf *bpn;
#if defined(MSDOSFSDEBUG)
printf("updateotherfats(pmp %08x, bp %08x, fatbn %d)\n",
#ifdef MSDOSFS_DEBUG
printf("updatefats(pmp %08x, bp %08x, fatbn %d)\n",
pmp, bp, fatbn);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* Now copy the block(s) of the modified fat to the other copies of
@ -302,6 +330,13 @@ updateotherfats(pmp, bp, fatbn)
else
bdwrite(bpn);
}
/*
* Write out the first fat last.
*/
if (pmp->pm_waitonfat)
bwrite(bp);
else
bdwrite(bp);
}
/*
@ -328,10 +363,9 @@ usemap_alloc(pmp, cn)
struct msdosfsmount *pmp;
u_long cn;
{
pmp->pm_inusemap[cn / 8] |= 1 << (cn % 8);
pmp->pm_inusemap[cn / N_INUSEBITS]
|= 1 << (cn % N_INUSEBITS);
pmp->pm_freeclustercount--;
/* This assumes that the lowest available cluster was allocated */
pmp->pm_lookhere = cn + 1;
}
extern __inline void
@ -340,9 +374,7 @@ usemap_free(pmp, cn)
u_long cn;
{
pmp->pm_freeclustercount++;
pmp->pm_inusemap[cn / 8] &= ~(1 << (cn % 8));
if (pmp->pm_lookhere > cn)
pmp->pm_lookhere = cn;
pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
}
int
@ -432,7 +464,9 @@ fatentry(function, pmp, cn, oldcontents, newcontents)
byteoffset = FATOFS(pmp, cn);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
if (error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp))
return error;
if (function & FAT_GET) {
readcn = getushort(&bp->b_data[bo]);
if (FAT12(pmp)) {
@ -458,14 +492,7 @@ fatentry(function, pmp, cn, oldcontents, newcontents)
putushort(&bp->b_data[bo], readcn);
} else
putushort(&bp->b_data[bo], newcontents);
updateotherfats(pmp, bp, bn);
/*
* Write out the first fat last.
*/
if (pmp->pm_waitonfat)
bwrite(bp);
else
bdwrite(bp);
updatefats(pmp, bp, bn);
bp = NULL;
pmp->pm_fmod = 1;
}
@ -475,49 +502,253 @@ fatentry(function, pmp, cn, oldcontents, newcontents)
}
/*
* Allocate a free cluster.
* Update a contiguous cluster chain
*
* pmp -
* retcluster - put the allocated cluster's number here.
* fillwith - put this value into the fat entry for the
* allocated cluster.
* pmp - mount point
* start - first cluster of chain
* count - number of clusters in chain
* fillwith - what to write into fat entry of last cluster
*/
int
clusteralloc(pmp, retcluster, fillwith)
static int
fatchain(pmp, start, count, fillwith)
struct msdosfsmount *pmp;
u_long *retcluster;
u_long start;
u_long count;
u_long fillwith;
{
int error;
u_long cn;
u_long idx, max_idx, bit, map;
max_idx = pmp->pm_maxcluster / 8;
for (idx = pmp->pm_lookhere / 8; idx <= max_idx; idx++) {
map = pmp->pm_inusemap[idx];
if (map != 0xff) {
for (bit = 0; bit < 8; bit++) {
if ((map & (1 << bit)) == 0) {
cn = idx * 8 + bit;
goto found_one;
u_long bn, bo, bsize, byteoffset, readcn, newc;
struct buf *bp;
#ifdef MSDOSFS_DEBUG
printf("fatchain(pmp %08x, start %d, count %d, fillwith %d)\n",
pmp, start, count, fillwith);
#endif
/*
* Be sure the clusters are in the filesystem.
*/
if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
return EINVAL;
while (count > 0) {
byteoffset = FATOFS(pmp, start);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
if (error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp))
return error;
while (count > 0) {
start++;
newc = --count > 0 ? start : fillwith;
if (FAT12(pmp)) {
readcn = getushort(&bp->b_data[bo]);
if (start & 1) {
readcn &= 0xf000;
readcn |= newc & 0xfff;
} else {
readcn &= 0x000f;
readcn |= newc << 4;
}
putushort(&bp->b_data[bo], readcn);
bo++;
if (!(start & 1))
bo++;
} else {
putushort(&bp->b_data[bo], newc);
bo += 2;
}
if (bo >= bsize)
break;
}
updatefats(pmp, bp, bn);
}
return ENOSPC;
pmp->pm_fmod = 1;
return 0;
}
found_one:;
error = fatentry(FAT_SET, pmp, cn, 0, fillwith);
if (error == 0) {
usemap_alloc(pmp, cn);
*retcluster = cn;
/*
* Check the length of a free cluster chain starting at start.
*
* pmp - mount point
* start - start of chain
* count - maximum interesting length
*/
int
chainlength(pmp, start, count)
struct msdosfsmount *pmp;
u_long start;
u_long count;
{
u_long idx, max_idx;
u_int map;
u_long len;
max_idx = (pmp->pm_maxcluster - 1) / N_INUSEBITS;
idx = start / N_INUSEBITS;
start %= N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map &= ~((1 << start) - 1);
if (map) {
len = ffs(map) - 1 - start;
return len > count ? count : len;
}
len = N_INUSEBITS - start;
if (len >= count)
return count;
while (++idx <= max_idx) {
if (len >= count)
break;
if (map = pmp->pm_inusemap[idx]) {
len += ffs(map) - 1;
break;
}
len += N_INUSEBITS;
}
return len > count ? count : len;
}
/*
* Allocate contigous free clusters.
*
* pmp - mount point.
* start - start of cluster chain.
* count - number of clusters to allocate.
* fillwith - put this value into the fat entry for the
* last allocated cluster.
* retcluster - put the first allocated cluster's number here.
* got - how many clusters were actually allocated.
*/
int
chainalloc(pmp, start, count, fillwith, retcluster, got)
struct msdosfsmount *pmp;
u_long start;
u_long count;
u_long fillwith;
u_long *retcluster;
u_long *got;
{
int error;
error = fatchain(pmp, start, count, fillwith);
if (error == 0) {
#ifdef MSDOSFS_DEBUG
printf("clusteralloc(): allocated cluster chain at %d (%d clusters)\n",
start, count);
#endif
if (retcluster)
*retcluster = start;
if (got)
*got = count;
while (count-- > 0)
usemap_alloc(pmp, start++);
}
#if defined(MSDOSFSDEBUG)
printf("clusteralloc(): allocated cluster %d\n", cn);
#endif /* defined(MSDOSFSDEBUG) */
return error;
}
/*
* Allocate contiguous free clusters.
*
* pmp - mount point.
* start - preferred start of cluster chain.
* count - number of clusters requested.
* fillwith - put this value into the fat entry for the
* last allocated cluster.
* retcluster - put the first allocated cluster's number here.
* got - how many clusters were actually allocated.
*/
int
clusteralloc(pmp, start, count, fillwith, retcluster, got)
struct msdosfsmount *pmp;
u_long start;
u_long count;
u_long fillwith;
u_long *retcluster;
u_long *got;
{
int error;
u_long idx, max_idx;
u_long len, newst, foundcn, foundl, cn, l;
u_int map;
#ifdef MSDOSFS_DEBUG
printf("clusteralloc(): find %d clusters\n",count);
#endif
if (start) {
if ((len = chainlength(pmp, start, count)) >= count)
return chainalloc(pmp, start, count, fillwith, retcluster, got);
} else {
/*
* This is a new file, initialize start
*/
struct timeval tv;
microtime(&tv);
start = (tv.tv_usec >> 10)|tv.tv_usec;
len = 0;
}
/*
* Start at a (pseudo) random place to maximize cluster runs
* under multiple writers.
*/
foundcn = newst = (start * 1103515245 + 12345) % (pmp->pm_maxcluster - 1);
foundl = 0;
max_idx = (pmp->pm_maxcluster - 1) / N_INUSEBITS;
idx = newst / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (newst % N_INUSEBITS)) - 1;
while (1) {
if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return chainalloc(pmp, cn, count, fillwith, retcluster, got);
if (l > foundl) {
foundcn = cn;
foundl = l;
}
cn += l + 1;
if (cn > pmp->pm_maxcluster)
break;
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
continue;
}
if (++idx > max_idx)
break;
map = pmp->pm_inusemap[idx];
}
for (idx = 0;;) {
map = pmp->pm_inusemap[idx];
if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count)
return chainalloc(pmp, cn, count, fillwith, retcluster, got);
if (l > foundl) {
foundcn = cn;
foundl = l;
}
cn += l + 1;
if (cn >= newst)
break;
idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1;
continue;
}
if (++idx * N_INUSEBITS >= newst)
break;
}
if (!foundl)
return ENOSPC;
if (len)
return chainalloc(pmp, start, len, fillwith, retcluster, got);
else
return chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got);
}
/*
* Free a chain of clusters.
*
@ -527,22 +758,48 @@ found_one:;
* freed.
*/
int
freeclusterchain(pmp, startcluster)
freeclusterchain(pmp, cluster)
struct msdosfsmount *pmp;
u_long startcluster;
u_long cluster;
{
u_long nextcluster;
int error = 0;
while (startcluster >= CLUST_FIRST && startcluster <= pmp->pm_maxcluster) {
error = clusterfree(pmp, startcluster, &nextcluster);
if (error) {
printf("freeclusterchain(): free failed, cluster %d\n",
startcluster);
break;
struct buf *bp = NULL;
u_long bn, bo, bsize, byteoffset;
u_long readcn, lbn = -1;
while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
byteoffset = FATOFS(pmp, cluster);
fatblock(pmp, byteoffset, &bn, &bsize, &bo);
if (lbn != bn) {
if (bp)
updatefats(pmp, bp, bn);
if (error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp))
return error;
lbn = bn;
}
usemap_free(pmp, cluster);
readcn = getushort(&bp->b_data[bo]);
if (FAT12(pmp)) {
if (cluster & 1) {
cluster = readcn >> 4;
readcn &= 0x000f;
readcn |= MSDOSFSFREE << 4;
} else {
cluster = readcn;
readcn &= 0xf000;
readcn |= MSDOSFSFREE & 0xfff;
}
putushort(&bp->b_data[bo], readcn);
cluster &= 0x0fff;
if ((cluster&0x0ff0) == 0x0ff0)
cluster |= 0xf000;
} else {
cluster = readcn;
putushort(&bp->b_data[bo], MSDOSFSFREE);
}
startcluster = nextcluster;
}
if (bp)
updatefats(pmp, bp, bn);
return error;
}
@ -564,8 +821,8 @@ fillinusemap(pmp)
* Mark all clusters in use, we mark the free ones in the fat scan
* loop further down.
*/
for (cn = 0; cn < (pmp->pm_maxcluster >> 3) + 1; cn++)
pmp->pm_inusemap[cn] = 0xff;
for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS - 1) / N_INUSEBITS; cn++)
pmp->pm_inusemap[cn] = (u_int)-1;
/*
* Figure how many free clusters are in the filesystem by ripping
@ -573,7 +830,6 @@ fillinusemap(pmp)
* zero. These represent free clusters.
*/
pmp->pm_freeclustercount = 0;
pmp->pm_lookhere = pmp->pm_maxcluster + 1;
for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) {
byteoffset = FATOFS(pmp, cn);
bo = byteoffset % pmp->pm_fatblocksize;
@ -603,27 +859,32 @@ fillinusemap(pmp)
/*
* Allocate a new cluster and chain it onto the end of the file.
*
* dep - the file to extend
* bpp - where to return the address of the buf header for the new
* file block
* ncp - where to put cluster number of the newly allocated file block
* If this pointer is 0, do not return the cluster number.
*
* NOTE: This function is not responsible for turning on the DEUPD bit of the
* dep - the file to extend
* count - number of clusters to allocate
* bpp - where to return the address of the buf header for the first new
* file block
* ncp - where to put cluster number of the first newly allocated cluster
* If this pointer is 0, do not return the cluster number.
* flags - see fat.h
*
* NOTE: This function is not responsible for turning on the DE_UPD bit of the
* de_flag field of the denode and it does not change the de_FileSize
* field. This is left for the caller to do.
*/
int
extendfile(dep, bpp, ncp)
extendfile(dep, count, bpp, ncp, flags)
struct denode *dep;
u_long count;
struct buf **bpp;
u_int *ncp;
u_long *ncp;
int flags;
{
int error = 0;
u_long frcn;
u_long cn;
u_long cn, got;
struct msdosfsmount *pmp = dep->de_pmp;
struct buf *bp;
/*
* Don't try to extend the root directory
*/
@ -646,52 +907,83 @@ extendfile(dep, bpp, ncp)
return error;
error = 0;
}
/*
* Allocate another cluster and chain onto the end of the file. If
* the file is empty we make de_StartCluster point to the new
* block. Note that de_StartCluster being 0 is sufficient to be
* sure the file is empty since we exclude attempts to extend the
* root directory above, and the root dir is the only file with a
* startcluster of 0 that has blocks allocated (sort of).
*/
if (error = clusteralloc(pmp, &cn, CLUST_EOFE))
return error;
if (dep->de_StartCluster == 0) {
dep->de_StartCluster = cn;
frcn = 0;
} else {
error = fatentry(FAT_SET, pmp, dep->de_fc[FC_LASTFC].fc_fsrcn,
0, cn);
if (error) {
clusterfree(pmp, cn, NULL);
while (count > 0) {
/*
* Allocate a new cluster chain and cat onto the end of the file.
* If the file is empty we make de_StartCluster point to the new
* block. Note that de_StartCluster being 0 is sufficient to be
* sure the file is empty since we exclude attempts to extend the
* root directory above, and the root dir is the only file with a
* startcluster of 0 that has blocks allocated (sort of).
*/
if (dep->de_StartCluster == 0)
cn = 0;
else
cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
if (error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got))
return error;
count -= got;
/*
* Give them the filesystem relative cluster number if they want
* it.
*/
if (ncp) {
*ncp = cn;
ncp = NULL;
}
if (dep->de_StartCluster == 0) {
dep->de_StartCluster = cn;
frcn = 0;
} else {
error = fatentry(FAT_SET, pmp, dep->de_fc[FC_LASTFC].fc_fsrcn,
0, cn);
if (error) {
clusterfree(pmp, cn, NULL);
return error;
}
frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
}
/*
* Update the "last cluster of the file" entry in the denode's fat
* cache.
*/
fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1);
if (flags & DE_CLEAR) {
while (got-- > 0) {
/*
* Get the buf header for the new block of the file.
*/
if (dep->de_Attributes & ATTR_DIRECTORY)
bp = getblk(pmp->pm_devvp, cntobn(pmp, cn++),
pmp->pm_bpcluster, 0, 0);
else {
bp = getblk(DETOV(dep), frcn++, pmp->pm_bpcluster, 0, 0);
/*
* Do the bmap now, as in msdosfs_write
*/
if (pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0))
bp->b_blkno = -1;
if (bp->b_blkno == -1)
panic("extendfile: pcbmap");
}
clrbuf(bp);
if (bpp) {
*bpp = bp;
bpp = NULL;
} else {
bp->b_flags |= B_AGE;
bawrite(bp);
}
}
}
frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
}
/*
* Update the "last cluster of the file" entry in the denode's fat
* cache.
*/
fc_setcache(dep, FC_LASTFC, frcn, cn);
/*
* Get the buf header for the new block of the file.
*/
if (dep->de_Attributes & ATTR_DIRECTORY)
*bpp = getblk(pmp->pm_devvp, cntobn(pmp, cn),
pmp->pm_bpcluster, 0, 0);
else
*bpp = getblk(DETOV(dep), frcn, pmp->pm_bpcluster, 0, 0);
clrbuf(*bpp);
/*
* Give them the filesystem relative cluster number if they want
* it.
*/
if (ncp)
*ncp = cn;
return 0;
}

View File

@ -1,5 +1,35 @@
/* $NetBSD: msdosfs_lookup.c,v 1.11 1994/07/16 21:33:23 cgd Exp $ */
/* $NetBSD: msdosfs_lookup.c,v 1.12 1994/07/18 21:38:16 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -80,18 +110,18 @@ msdosfs_lookup(ap)
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr);
#endif /* defined(MSDOSFSDEBUG) */
#endif
dp = VTODE(vdp);
pmp = dp->de_pmp;
*vpp = NULL;
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT | WANTPARENT);
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): vdp %08x, dp %08x, Attr %02x\n",
vdp, dp, dp->de_Attributes);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* Be sure vdp is a directory. Since dos filesystems don't have
@ -130,9 +160,10 @@ msdosfs_lookup(ap)
if (!error) {
if (vpid == vdp->v_id) {
#if defined(MSDOSFSDEBUG)
printf("msdosfs_lookup(): cache hit, vnode %08x, file %s\n", vdp, dp->de_Name);
#endif /* defined(MSDOSFSDEBUG) */
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): cache hit, vnode %08x, file %s\n",
vdp, dp->de_Name);
#endif
return 0;
}
vput(vdp);
@ -156,9 +187,9 @@ msdosfs_lookup(ap)
(cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) {
isadir = ATTR_DIRECTORY;
scn = MSDOSFSROOT;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): looking for . or .. in root directory\n");
#endif /* defined(MSDOSFSDEBUG) */
#endif
cluster = MSDOSFSROOT;
diroff = MSDOSFSROOT_OFS;
goto foundroot;
@ -176,10 +207,10 @@ msdosfs_lookup(ap)
unix2dosfn((u_char *) cnp->cn_nameptr, dosfilename, cnp->cn_namelen);
dosfilename[11] = 0;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): dos version of filename %s, length %d\n",
dosfilename, cnp->cn_namelen);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* Search the directory pointed at by vdp for the name pointed at
* by cnp->cn_nameptr.
@ -234,9 +265,10 @@ msdosfs_lookup(ap)
*/
if ((dep->deAttributes & ATTR_VOLUME) == 0 &&
bcmp(dosfilename, dep->deName, 11) == 0) {
#if defined(MSDOSFSDEBUG)
printf("msdosfs_lookup(): match diroff %d, rootreloff %d\n", diroff, rootreloff);
#endif /* defined(MSDOSFSDEBUG) */
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): match diroff %d, rootreloff %d\n",
diroff, rootreloff);
#endif
/*
* Remember where this directory
* entry came from for whoever did
@ -271,25 +303,25 @@ notfound:;
* that's ok if we are creating or renaming and are at the end of
* the pathname and the directory hasn't been removed.
*/
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): op %d, refcnt %d, slotstatus %d\n",
nameiop, dp->de_refcnt, slotstatus);
printf(" slotoffset %d, slotcluster %d\n",
slotoffset, slotcluster);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if ((nameiop == CREATE || nameiop == RENAME) &&
(flags & ISLASTCN) && dp->de_refcnt != 0) {
if (slotstatus == NONE) {
dp->de_fndoffset = (u_long)-1;
dp->de_fndclust = (u_long)-1;
} else {
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_lookup(): saving empty slot location\n");
#endif /* defined(MSDOSFSDEBUG) */
#endif
dp->de_fndoffset = slotoffset;
dp->de_fndclust = slotcluster;
}
/* dp->de_flag |= DEUPD; /* never update dos directories */
/* dp->de_flag |= DE_UPD; /* never update dos directories */
cnp->cn_flags |= SAVENAME;
if (!lockparent)/* leave searched dir locked? */
VOP_UNLOCK(vdp);
@ -432,9 +464,9 @@ createde(dep, ddep, depp)
struct msdosfsmount *pmp = ddep->de_pmp;
struct buf *bp;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("createde(dep %08x, ddep %08x, depp %08x)\n", dep, ddep, depp);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* If no space left in the directory then allocate another cluster
@ -445,7 +477,7 @@ createde(dep, ddep, depp)
* case.
*/
if (ddep->de_fndclust == (u_long)-1) {
if (error = extendfile(ddep, &bp, &dirclust))
if (error = extendfile(ddep, 1, &bp, &dirclust, DE_CLEAR))
return error;
ndep = (struct direntry *) bp->b_data;
/*
@ -482,7 +514,7 @@ createde(dep, ddep, depp)
return error;
}
if (error = bwrite(bp)) {
deput(*depp); /* free the vnode we got on error */
vput(DETOV(*depp)); /* free the vnode we got on error */
return error;
}
return 0;
@ -524,15 +556,11 @@ removede(pdep,dep)
struct msdosfsmount *pmp = pdep->de_pmp;
int error;
#if defined(MSDOSFSDEBUG)
/*
* printf("removede(): filename %s\n", dep->de_Name);
* printf("removede(): dep %08x, ndpcluster %d, ndpoffset %d\n",
* dep,
* pdep->de_fndclust,
* pdep->de_fndoffset);
*/
#endif /* defined(MSDOSFSDEBUG) */
#ifdef MSDOSFS_DEBUG
printf("removede(): filename %s\n", dep->de_Name);
printf("removede(): dep %08x, ndpcluster %d, ndpoffset %d\n",
dep, pdep->de_fndclust, pdep->de_fndoffset);
#endif
/*
* Read the directory block containing the directory entry we are
@ -596,10 +624,10 @@ dosdirempty(dep)
if (bcmp(dentp->deName, ". ", 11) &&
bcmp(dentp->deName, ".. ", 11)) {
brelse(bp);
#if defined(MSDOSFSDEBUG)
printf("dosdirempty(): entry %d found %02x, %02x\n", dei, dentp->deName[0],
dentp->deName[1]);
#endif /* defined(MSDOSFSDEBUG) */
#ifdef MSDOSFS_DEBUG
printf("dosdirempty(): entry %d found %02x, %02x\n",
dei, dentp->deName[0], dentp->deName[1]);
#endif
return 0; /* not empty */
}
}
@ -673,7 +701,7 @@ doscheckpath(source, target)
}
if (scn == MSDOSFSROOT)
break;
deput(dep);
vput(DETOV(dep));
/* NOTE: deget() clears dep on error */
error = deget(pmp, scn, 0, ep, &dep);
brelse(bp);
@ -687,7 +715,7 @@ out: ;
if (error == ENOTDIR)
printf("doscheckpath(): .. not a directory?\n");
if (dep != NULL)
deput(dep);
vput(DETOV(dep));
return error;
}

View File

@ -1,5 +1,35 @@
/* $NetBSD: msdosfs_vfsops.c,v 1.16 1994/07/16 21:33:24 cgd Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.17 1994/07/18 21:38:18 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -195,9 +225,9 @@ msdosfs_mount(mp, path, data, ndp, p)
pmp->pm_uid = args.uid;
pmp->pm_mask = args.mask;
(void) msdosfs_statfs(mp, &mp->mnt_stat, p);
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap);
#endif /* defined(MSDOSFSDEBUG) */
#endif
return 0;
}
@ -239,14 +269,14 @@ mountmsdosfs(devvp, mp, p)
if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE, FSCRED, p))
return error;
needclose = 1;
#if defined(HDSUPPORT)
#ifdef HDSUPPORT
/*
* Put this in when we support reading dos filesystems from
* partitioned harddisks.
*/
if (VOP_IOCTL(devvp, DIOCGPART, &msdosfspart, FREAD, NOCRED, p) == 0) {
}
#endif /* defined(HDSUPPORT) */
#endif
/*
* Read the boot sector of the filesystem, and then check the boot
@ -375,8 +405,10 @@ mountmsdosfs(devvp, mp, p)
* Allocate memory for the bitmap of allocated clusters, and then
* fill it in.
*/
pmp->pm_inusemap = malloc((pmp->pm_maxcluster >> 3) + 1,
M_MSDOSFSFAT, M_WAITOK);
pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1)
/ N_INUSEBITS)
* sizeof(*pmp->pm_inusemap),
M_MSDOSFSFAT, M_WAITOK);
/*
* fillinusemap() needs pm_devvp.
@ -409,7 +441,7 @@ mountmsdosfs(devvp, mp, p)
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_MSDOS);
mp->mnt_flag |= MNT_LOCAL;
#if defined(QUOTA)
#ifdef QUOTA
/*
* If we ever do quotas for DOS filesystems this would be a place
* to fill in the info in the msdosfsmount structure. You dolt,
@ -417,7 +449,7 @@ mountmsdosfs(devvp, mp, p)
* owners on dos filesystems. of course there is some empty space
* in the directory entry where we could put uid's and gid's.
*/
#endif /* defined(QUOTA) */
#endif
devvp->v_specflags |= SI_MOUNTEDON;
return 0;
@ -470,12 +502,12 @@ msdosfs_unmount(mp, mntflags, p)
return EINVAL;
flags |= FORCECLOSE;
}
#if defined(QUOTA)
#endif /* defined(QUOTA) */
#ifdef QUOTA
#endif
if (error = vflush(mp, NULLVP, flags))
return error;
pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n",
vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
@ -487,7 +519,7 @@ msdosfs_unmount(mp, mntflags, p)
vp->v_cleanblkhd, vp->v_dirtyblkhd, vp->v_numoutput, vp->v_type);
printf("union %08x, tag %d, data[0] %08x, data[1] %08x\n",
vp->v_socket, vp->v_tag, vp->v_data[0], vp->v_data[1]);
#endif /* defined(MSDOSFSDEBUG) */
#endif
error = VOP_CLOSE(pmp->pm_devvp, pmp->pm_ronly ? FREAD : FREAD | FWRITE,
NOCRED, p);
vrele(pmp->pm_devvp);
@ -508,10 +540,10 @@ msdosfs_root(mp, vpp)
int error;
error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, NULL, &ndep);
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_root(); mp %08x, pmp %08x, ndep %08x, vp %08x\n",
mp, pmp, ndep, DETOV(ndep));
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (error == 0)
*vpp = DETOV(ndep);
return error;
@ -525,10 +557,10 @@ msdosfs_quotactl(mp, cmds, uid, arg, p)
caddr_t arg;
struct proc *p;
{
#if defined(QUOTA)
#ifdef QUOTA
#else
return EOPNOTSUPP;
#endif /* defined(QUOTA) */
#endif
}
int
@ -608,7 +640,7 @@ loop:
if (VOP_ISLOCKED(vp)) /* file is busy */
continue;
dep = VTODE(vp);
if ((dep->de_flag & DEUPD) == 0 &&
if ((dep->de_flag & DE_UPD) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
if (vget(vp, 1)) /* not there anymore? */

View File

@ -1,5 +1,35 @@
/* $NetBSD: msdosfs_vnops.c,v 1.15 1994/07/16 21:33:27 cgd Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.16 1994/07/18 21:38:20 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -76,9 +106,9 @@ msdosfs_create(ap)
struct timespec ts;
int error;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_create(cnp %08x, vap %08x\n", cnp, ap->a_vap);
#endif /* defined(MSDOSFSDEBUG) */
#endif
/*
* Create a directory entry for the file, then call createde() to
@ -86,7 +116,7 @@ msdosfs_create(ap)
* use the absence of the owner write bit to make the file
* readonly.
*/
#ifdef DIAGNOSITC
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & SAVENAME) == 0)
panic("msdosfs_create: no name");
#endif
@ -106,7 +136,7 @@ msdosfs_create(ap)
} else {
free(cnp->cn_pnbuf, M_NAMEI);
}
deput(pdep); /* release parent dir */
vput(ap->a_dvp); /* release parent dir */
return error;
}
@ -134,7 +164,7 @@ msdosfs_mknod(ap)
default:
error = EINVAL;
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
deput(pdep);
vput(ap->a_dvp);
break;
}
return error;
@ -165,13 +195,71 @@ msdosfs_close(ap)
struct denode *dep = VTODE(vp);
struct timespec ts;
if (vp->v_usecount > 1 && !(dep->de_flag & DELOCKED)) {
if (vp->v_usecount > 1 && !(dep->de_flag & DE_LOCKED)) {
TIMEVAL_TO_TIMESPEC(&time, &ts);
DETIMES(dep, &ts);
DE_TIMES(dep, &ts);
}
return 0;
}
/*
* This routine will go into sys/kern/vfs_subr.c one day!
*
* Do the usual access checking.
* file_node, uid and gid are from the vnode in question,
* while acc_mode and cred are from the VOP_ACCESS parameter list.
*/
static
vaccess(file_mode, uid, gid, acc_mode, cred)
mode_t file_mode;
uid_t uid;
gid_t gid;
mode_t acc_mode;
struct ucred *cred;
{
mode_t mask;
int i;
register gid_t *gp;
/* User id 0 always gets access. */
if (cred->cr_uid == 0)
return 0;
mask = 0;
/* Otherwise, check the owner. */
if (cred->cr_uid == uid) {
if (acc_mode & VEXEC)
mask |= S_IXUSR;
if (acc_mode & VREAD)
mask |= S_IRUSR;
if (acc_mode & VWRITE)
mask |= S_IWUSR;
return (file_mode & mask) == mask ? 0 : EACCES;
}
/* Otherwise, check the groups. */
for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
if (gid == *gp) {
if (acc_mode & VEXEC)
mask |= S_IXGRP;
if (acc_mode & VREAD)
mask |= S_IRGRP;
if (acc_mode & VWRITE)
mask |= S_IWGRP;
return (file_mode & mask) == mask ? 0 : EACCES;
}
/* Otherwise, check everyone else. */
if (acc_mode & VEXEC)
mask |= S_IXOTH;
if (acc_mode & VREAD)
mask |= S_IROTH;
if (acc_mode & VWRITE)
mask |= S_IWOTH;
return (file_mode & mask) == mask ? 0 : EACCES;
}
int
msdosfs_access(ap)
struct vop_access_args /* {
@ -181,28 +269,15 @@ msdosfs_access(ap)
struct proc *a_p;
} */ *ap;
{
int dosmode;
mode_t dosmode;
struct denode *dep = VTODE(ap->a_vp);
/*
* Root gets to do anything. Even execute a file without the x-bit
* on? But, for dos filesystems every file is executable. I may
* regret this.
*/
if (ap->a_cred->cr_uid == 0)
return 0;
/*
* mode is filled with a combination of VREAD, VWRITE, and/or VEXEC
* bits turned on. In an octal number these are the Y in 0Y00.
*
* Since the dos filesystem doesn't have the concept of file ownership
* we just give everybody read and execute access and write access
* if the readonly bit is off.
*/
dosmode = VEXEC | VREAD |
((dep->de_Attributes & ATTR_READONLY) ? 0 : VWRITE);
return ((dosmode & ap->a_mode) != 0) ? 0 : EACCES;
struct msdosfsmount *pmp = dep->de_pmp;
dosmode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) |
((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH));
dosmode &= pmp->pm_mask;
return vaccess(dosmode, pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred);
}
int
@ -220,7 +295,7 @@ msdosfs_getattr(ap)
struct timespec ts;
TIMEVAL_TO_TIMESPEC(&time, &ts);
DETIMES(dep, &ts);
DE_TIMES(dep, &ts);
vap->va_fsid = dep->de_dev;
/*
* The following computation of the fileid must be the same as that
@ -236,7 +311,8 @@ msdosfs_getattr(ap)
cn = (cn << 16) | (dep->de_diroffset & 0xffff);
}
vap->va_fileid = cn;
vap->va_mode = (dep->de_Attributes & ATTR_READONLY) ? 0555 : 0777;
vap->va_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) |
((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH));
vap->va_mode &= dep->de_pmp->pm_mask;
if (dep->de_Attributes & ATTR_DIRECTORY)
vap->va_mode |= S_IFDIR;
@ -275,10 +351,10 @@ msdosfs_setattr(ap)
struct vattr *vap = ap->a_vap;
struct ucred *cred = ap->a_cred;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_setattr(): vp %08x, vap %08x, cred %08x, p %08x\n",
ap->a_vp, vap, cred, ap->a_p);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if ((vap->va_type != VNON) ||
(vap->va_nlink != VNOVAL) ||
(vap->va_fsid != VNOVAL) ||
@ -288,17 +364,16 @@ msdosfs_setattr(ap)
(vap->va_bytes != VNOVAL) ||
(vap->va_gen != VNOVAL) ||
(vap->va_uid != VNOVAL) ||
(vap->va_gid != VNOVAL) ||
(vap->va_atime.ts_sec != VNOVAL)) {
#if defined(MSDOSFSDEBUG)
(vap->va_gid != VNOVAL)) {
#ifdef MSDOSFS_DEBUG
printf("msdosfs_setattr(): returning EINVAL\n");
printf(" va_type %d, va_nlink %x, va_fsid %x, va_fileid %x\n",
vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid);
printf(" va_blocksize %x, va_rdev %x, va_bytes %x, va_gen %x\n",
vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen);
printf(" va_uid %x, va_gid %x, va_atime.ts_sec %x\n",
vap->va_uid, vap->va_gid, vap->va_atime.ts_sec);
#endif /* defined(MSDOSFSDEBUG) */
printf(" va_uid %x, va_gid %x\n",
vap->va_uid, vap->va_gid);
#endif
return EINVAL;
}
@ -309,7 +384,7 @@ msdosfs_setattr(ap)
return error;
}
if (vap->va_mtime.ts_sec != VNOVAL) {
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
if (error = deupdat(dep, &vap->va_mtime, 1))
return error;
}
@ -325,7 +400,7 @@ msdosfs_setattr(ap)
dep->de_Attributes &= ~ATTR_READONLY;
else
dep->de_Attributes |= ATTR_READONLY;
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
}
if (vap->va_flags != VNOVAL) {
@ -337,7 +412,7 @@ msdosfs_setattr(ap)
dep->de_flag &= 0xffff0000;
dep->de_flag |= (vap->va_flags & 0xffff);
}
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
}
return error;
}
@ -448,10 +523,8 @@ msdosfs_write(ap)
int resid;
int osize;
int error;
u_long cluster;
u_long nextcluster;
u_long lastcluster;
daddr_t bn;
u_long count;
daddr_t bn, lastcn;
struct buf *bp;
int ioflag = ap->a_ioflag;
struct uio *uio = ap->a_uio;
@ -462,12 +535,12 @@ msdosfs_write(ap)
struct msdosfsmount *pmp = dep->de_pmp;
struct ucred *cred = ap->a_cred;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_write(vp %08x, uio %08x, ioflag %08x, cred %08x\n",
vp, uio, ioflag, cred);
printf("msdosfs_write(): diroff %d, dirclust %d, startcluster %d\n",
dep->de_diroffset, dep->de_dirclust, dep->de_StartCluster);
#endif /* defined(MSDOSFSDEBUG) */
#endif
switch (vp->v_type) {
case VREG:
@ -532,31 +605,65 @@ msdosfs_write(ap)
resid = uio->uio_resid;
osize = dep->de_FileSize;
/*
* If we write beyond the end of the file, extend it to its ultimate
* size ahead of the time to hopefully get a contiguous area.
*/
if (uio->uio_offset + resid > osize) {
count = de_clcount(pmp, uio->uio_offset + resid) - de_clcount(pmp, osize);
if ((error = extendfile(dep, count, NULL, NULL, 0))
&& (error != ENOSPC || (ioflag & IO_UNIT)))
goto errexit;
lastcn = dep->de_fc[FC_LASTFC].fc_frcn;
} else
lastcn = de_clcount(pmp, osize) - 1;
do {
bn = uio->uio_offset >> pmp->pm_cnshift;
/*
* If we are appending to the file and we are on a cluster
* boundary, then allocate a new cluster and chain it onto
* the file.
*/
if (uio->uio_offset == dep->de_FileSize &&
(uio->uio_offset & pmp->pm_crbomask) == 0) {
if (error = extendfile(dep, &bp, 0))
bn = de_blk(pmp, uio->uio_offset);
if (isadir) {
if (error = pcbmap(dep, bn, &bn, 0))
break;
} else if (bn > lastcn) {
error = ENOSPC;
break;
}
if ((uio->uio_offset & pmp->pm_crbomask) == 0
&& (de_blk(pmp, uio->uio_offset + uio->uio_resid) > de_blk(pmp, uio->uio_offset)
|| uio->uio_offset + uio->uio_resid >= dep->de_FileSize)) {
/*
* If either the whole cluster gets written,
* or we write the cluster from its start beyond EOF,
* then no need to read data from disk.
*/
bp = getblk(thisvp, bn, pmp->pm_bpcluster, 0, 0);
clrbuf(bp);
/*
* Do the bmap now, since pcbmap needs buffers
* for the fat table. (see msdosfs_strategy)
*/
if (!isadir) {
if (bp->b_blkno == bp->b_lblkno) {
if (error = pcbmap(dep, bp->b_lblkno,
&bp->b_blkno, 0))
bp->b_blkno = -1;
}
if (bp->b_blkno == -1) {
brelse(bp);
if (!error)
error = EIO; /* XXX */
break;
}
}
} else {
/*
* The block we need to write into exists, so just
* read it in.
* The block we need to write into exists, so read it in.
*/
if (isadir) {
error = pcbmap(dep, bn, &bn, 0);
if (error)
return error;
}
error = bread(thisvp, bn, pmp->pm_bpcluster, cred, &bp);
if (error)
return error;
if (error = bread(thisvp, bn, pmp->pm_bpcluster, cred, &bp))
break;
}
croffset = uio->uio_offset & pmp->pm_crbomask;
n = min(uio->uio_resid, pmp->pm_bpcluster - croffset);
if (uio->uio_offset + n > dep->de_FileSize) {
@ -588,20 +695,28 @@ msdosfs_write(ap)
bawrite(bp);
} else
bdwrite(bp);
dep->de_flag |= DEUPD;
dep->de_flag |= DE_UPD;
} while (error == 0 && uio->uio_resid > 0);
/*
* If the write failed and they want us to, truncate the file back
* to the size it was before the write was attempted.
*/
if (error && (ioflag & IO_UNIT)) {
detrunc(dep, osize, ioflag & IO_SYNC, NOCRED, NULL);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
errexit:
if (error) {
if (ioflag & IO_UNIT) {
detrunc(dep, osize, ioflag & IO_SYNC, NOCRED, NULL);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
} else {
detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED, NULL);
if (uio->uio_resid != resid)
error = 0;
}
} else {
if (ioflag & IO_UNIT)
error = deupdat(dep, &time, 1);
}
if (!error && (ioflag & IO_UNIT))
error = deupdat(dep, &time, 1);
return error;
}
@ -700,15 +815,15 @@ msdosfs_remove(ap)
struct denode *ddep = VTODE(ap->a_dvp);
error = removede(ddep,dep);
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_remove(), dep %08x, v_usecount %d\n", dep, ap->a_vp->v_usecount);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (ddep == dep)
vrele(DETOV(dep));
vrele(ap->a_vp);
else
deput(dep); /* causes msdosfs_inactive() to be called
vput(ap->a_vp); /* causes msdosfs_inactive() to be called
* via vrele() */
deput(ddep);
vput(ap->a_dvp);
return error;
}
@ -876,10 +991,10 @@ msdosfs_rename(ap)
newparent = 1;
if (sourceisadirectory && newparent) {
if (tdep) {
deput(tdep);
vput(ap->a_tvp);
tdep = NULL;
}
/* doscheckpath() deput()'s tddep */
/* doscheckpath() vput()'s tddep */
error = doscheckpath(fdep, tddep);
tddep = NULL;
if (error) {
@ -920,7 +1035,7 @@ msdosfs_rename(ap)
if (error = removede(tddep,tdep)) {
goto bad;
}
deput(tdep);
vput(ap->a_tvp);
tdep = NULL;
/*
@ -937,17 +1052,17 @@ msdosfs_rename(ap)
*/
if (newparent == 0) {
/* tddep and fddep point to the same denode here */
DELOCK(fdep); /* fddep is already locked */
VOP_LOCK(ap->a_fvp); /* ap->a_fdvp is already locked */
if (error = readep(fddep->de_pmp,
fddep->de_fndclust,
fddep->de_fndoffset,
&bp, &ep)) {
DEUNLOCK(fdep);
VOP_UNLOCK(ap->a_fvp);
goto bad;
}
bcopy(toname, ep->deName, 11);
if (error = bwrite(bp)) {
DEUNLOCK(fdep);
VOP_UNLOCK(ap->a_fvp);
goto bad;
}
bcopy(toname, fdep->de_Name, 11); /* update denode */
@ -969,7 +1084,7 @@ msdosfs_rename(ap)
* will also insure that the directory entry on disk has a
* filesize of zero.
*/
DELOCK(fdep);
VOP_LOCK(ap->a_fvp);
bcopy(toname, fdep->de_Name, 11); /* update denode */
if (fdep->de_Attributes & ATTR_DIRECTORY) {
dirsize = fdep->de_FileSize;
@ -981,28 +1096,28 @@ msdosfs_rename(ap)
}
if (error) {
/* should put back filename */
DEUNLOCK(fdep);
VOP_UNLOCK(ap->a_fvp);
goto bad;
}
DELOCK(fddep);
VOP_LOCK(ap->a_fdvp);
if (error = readep(fddep->de_pmp,
fddep->de_fndclust,
fddep->de_fndoffset,
&bp, &ep)) {
DEUNLOCK(fdep);
DEUNLOCK(fddep);
VOP_UNLOCK(ap->a_fvp);
VOP_UNLOCK(ap->a_fdvp);
goto bad;
}
ep->deName[0] = SLOT_DELETED;
if (error = bwrite(bp)) {
DEUNLOCK(fdep);
DEUNLOCK(fddep);
VOP_UNLOCK(ap->a_fvp);
VOP_UNLOCK(ap->a_fdvp);
goto bad;
}
fdep->de_dirclust = tddep->de_fndclust;
fdep->de_diroffset = tddep->de_fndoffset;
reinsert(fdep);
DEUNLOCK(fddep);
VOP_UNLOCK(ap->a_fdvp);
}
/* fdep is still locked here */
@ -1022,20 +1137,19 @@ msdosfs_rename(ap)
NOCRED, &bp);
if (error) {
/* should really panic here, fs is corrupt */
DEUNLOCK(fdep);
VOP_UNLOCK(ap->a_fvp);
goto bad;
}
dotdotp = (struct direntry *) bp->b_data + 1;
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
error = bwrite(bp);
DEUNLOCK(fdep);
VOP_UNLOCK(ap->a_fvp);
if (error) {
/* should really panic here, fs is corrupt */
goto bad;
}
} else {
DEUNLOCK(fdep);
}
} else
VOP_UNLOCK(ap->a_fvp);
bad: ;
vrele(DETOV(fdep));
vrele(DETOV(fddep));
@ -1079,7 +1193,6 @@ msdosfs_mkdir(ap)
u_long newcluster;
struct denode *pdep;
struct denode *ndep;
struct vnode *pvp;
struct direntry *denp;
struct denode ndirent;
struct msdosfsmount *pmp;
@ -1087,8 +1200,7 @@ msdosfs_mkdir(ap)
struct timespec ts;
u_short dDate, dTime;
pvp = ap->a_dvp;
pdep = VTODE(pvp);
pdep = VTODE(ap->a_dvp);
/*
* If this is the root directory and there is no space left we
@ -1097,7 +1209,7 @@ msdosfs_mkdir(ap)
*/
if (pdep->de_StartCluster == MSDOSFSROOT && pdep->de_fndclust == (u_long)-1) {
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
deput(pdep);
vput(ap->a_dvp);
return ENOSPC;
}
@ -1106,9 +1218,9 @@ msdosfs_mkdir(ap)
/*
* Allocate a cluster to hold the about to be created directory.
*/
if (error = clusteralloc(pmp, &newcluster, CLUST_EOFE)) {
if (error = clusteralloc(pmp, 0, 1, CLUST_EOFE, &newcluster, NULL)) {
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
deput(pdep);
vput(ap->a_dvp);
return error;
}
@ -1135,7 +1247,7 @@ msdosfs_mkdir(ap)
if (error = bwrite(bp)) {
clusterfree(pmp, newcluster, NULL);
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
deput(pdep);
vput(ap->a_dvp);
return error;
}
@ -1160,10 +1272,10 @@ msdosfs_mkdir(ap)
*ap->a_vpp = DETOV(ndep);
}
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
#if defined(MSDOSFSDEBUG)
printf("msdosfs_mkdir(): deput(%08x), vnode %08x\n", pdep, DETOV(pdep));
#endif /* defined(MSDOSFSDEBUG) */
deput(pdep);
#ifdef MSDOSFS_DEBUG
printf("msdosfs_mkdir(): vput(%08x)\n", ap->a_dvp);
#endif
vput(ap->a_dvp);
return error;
}
@ -1186,8 +1298,8 @@ msdosfs_rmdir(ap)
* Don't let "rmdir ." go thru.
*/
if (ddep == dep) {
vrele(DETOV(dep));
deput(dep);
vrele(ap->a_vp);
vput(ap->a_vp);
return EINVAL;
}
@ -1203,7 +1315,7 @@ msdosfs_rmdir(ap)
* Delete the entry from the directory. For dos filesystems this
* gets rid of the directory entry on disk, the in memory copy
* still exists but the de_refcnt is <= 0. This prevents it from
* being found by deget(). When the deput() on dep is done we give
* being found by deget(). When the vput() on dep is done we give
* up access and eventually msdosfs_reclaim() will be called which
* will remove it from the denode cache.
*/
@ -1216,7 +1328,7 @@ msdosfs_rmdir(ap)
* the name cache and let go of the parent directory denode.
*/
cache_purge(DETOV(ddep));
deput(ddep);
vput(ap->a_dvp);
ap->a_dvp = NULL;
/*
@ -1227,8 +1339,8 @@ msdosfs_rmdir(ap)
out: ;
if (ap->a_dvp)
deput(ddep);
deput(dep);
vput(ap->a_dvp);
vput(ap->a_vp);
return error;
}
@ -1248,7 +1360,7 @@ msdosfs_symlink(ap)
struct denode *pdep = VTODE(ap->a_dvp);
free(ap->a_cnp->cn_pnbuf, M_NAMEI);
deput(pdep);
vput(ap->a_dvp);
return EINVAL;
}
@ -1311,10 +1423,10 @@ msdosfs_readdir(ap)
int i = 0;
struct uio *uio = ap->a_uio;
#if defined(MSDOSFSDEBUG)
#ifdef MSDOSFS_DEBUG
printf("msdosfs_readdir(): vp %08x, uio %08x, cred %08x, eofflagp %08x\n",
ap->a_vp, uio, ap->a_cred, ap->a_eofflag);
#endif /* defined(MSDOSFSDEBUG) */
#endif
if (!ap->a_cookies)
ap->a_ncookies = 1;
@ -1565,7 +1677,16 @@ msdosfs_lock(ap)
{
struct denode *dep = VTODE(ap->a_vp);
DELOCK(dep);
while (dep->de_flag & DE_LOCKED) {
dep->de_flag |= DE_WANT;
if (dep->de_lockholder == curproc->p_pid)
panic("msdosfs_lock: locking against myself");
dep->de_lockwaiter = curproc->p_pid;
(void) sleep((caddr_t) dep, PINOD);
}
dep->de_lockwaiter = 0;
dep->de_lockholder = curproc->p_pid;
dep->de_flag |= DE_LOCKED;
return 0;
}
@ -1577,9 +1698,14 @@ msdosfs_unlock(ap)
{
struct denode *dep = VTODE(ap->a_vp);
if (!(dep->de_flag & DELOCKED))
if (!(dep->de_flag & DE_LOCKED))
panic("msdosfs_unlock: denode not locked");
DEUNLOCK(dep);
dep->de_lockholder = 0;
dep->de_flag &= ~DE_LOCKED;
if (dep->de_flag & DE_WANT) {
dep->de_flag &= ~DE_WANT;
wakeup((caddr_t) dep);
}
return 0;
}
@ -1589,7 +1715,7 @@ msdosfs_islocked(ap)
struct vnode *a_vp;
} */ *ap;
{
return VTODE(ap->a_vp)->de_flag & DELOCKED ? 1 : 0;
return VTODE(ap->a_vp)->de_flag & DE_LOCKED ? 1 : 0;
}
/*
@ -1646,7 +1772,7 @@ msdosfs_strategy(ap)
struct denode *dep = VTODE(bp->b_vp);
struct msdosfsmount *pmp = dep->de_pmp;
struct vnode *vp;
int error;
int error = 0;
if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
panic("msdosfs_strategy: spec");
@ -1658,16 +1784,16 @@ msdosfs_strategy(ap)
*/
if (bp->b_blkno == bp->b_lblkno) {
if (error = pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0))
return error;
if ((long) bp->b_blkno == -1)
bp->b_blkno = -1;
if (bp->b_blkno == -1)
clrbuf(bp);
}
if ((long) bp->b_blkno == -1) {
if (bp->b_blkno == -1) {
biodone(bp);
return 0;
return error;
}
#ifdef DIAGNOSTIC
#endif /* defined(DIAGNOSTIC) */
#endif
/*
* Read/write the block from/to the disk that contains the desired
* file block.
@ -1690,7 +1816,7 @@ msdosfs_print(ap)
dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset);
printf(" dev %d, %d, %s\n",
major(dep->de_dev), minor(dep->de_dev),
dep->de_flag & DELOCKED ? "(LOCKED)" : "");
dep->de_flag & DE_LOCKED ? "(LOCKED)" : "");
if (dep->de_lockholder) {
printf(" owner pid %d", dep->de_lockholder);
if (dep->de_lockwaiter)

View File

@ -1,5 +1,35 @@
/* $NetBSD: msdosfsmount.h,v 1.5 1994/07/16 21:33:29 cgd Exp $ */
/* $NetBSD: msdosfsmount.h,v 1.6 1994/07/18 21:38:22 cgd Exp $ */
/*-
* Copyright (C) 1994 Wolfgang Solfrank.
* Copyright (C) 1994 TooLs GmbH.
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
*/
/*
* Written by Paul Popelka (paulp@uts.amdahl.com)
*
@ -35,7 +65,6 @@ struct msdosfsmount {
u_long pm_nmbrofclusters; /* # of clusters in filesystem */
u_long pm_maxcluster; /* maximum cluster number */
u_long pm_freeclustercount; /* number of free clusters */
u_long pm_lookhere; /* start free cluster search here */
u_long pm_bnshift; /* shift file offset right this amount to get a block number */
u_long pm_brbomask; /* and a file offset with this mask to get block rel offset */
u_long pm_cnshift; /* shift file offset right this amount to get a cluster number */
@ -46,12 +75,15 @@ struct msdosfsmount {
u_long pm_fatblocksize; /* size of fat blocks in bytes */
u_long pm_fatblocksec; /* size of fat blocks in sectors */
u_long pm_fatsize; /* size of fat in bytes */
u_char *pm_inusemap; /* ptr to bitmap of in-use clusters */
u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */
char pm_ronly; /* read only if non-zero */
char pm_waitonfat; /* wait for writes of the fat to complt, when 0 use bdwrite, else use bwrite */
struct netexport pm_export; /* export information */
};
/* Number of bits in one pm_inusemap item: */
#define N_INUSEBITS (8 * sizeof(u_int))
/*
* How to compute pm_cnshift and pm_crbomask.
*
@ -122,6 +154,18 @@ struct msdosfsmount {
+ (dirofs) % (pmp)->pm_depclust)
/*
* Convert filesize to block number
*/
#define de_blk(pmp, off) \
((off) >> (pmp)->pm_cnshift)
/*
* Clusters required to hold size bytes
*/
#define de_clcount(pmp, size) \
(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)
/*
* Prototypes for MSDOSFS virtual filesystem operations
*/