[BACK]Return to msdosfs_denode.c CVS log [TXT][DIR] Up to [local] / sys / msdosfs

Annotation of sys/msdosfs/msdosfs_denode.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: msdosfs_denode.c,v 1.32 2007/06/02 02:04:21 deraadt Exp $     */
        !             2: /*     $NetBSD: msdosfs_denode.c,v 1.23 1997/10/17 11:23:58 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:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by TooLs GmbH.
        !            21:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
        !            22:  *    derived from this software without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
        !            25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            27:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            28:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            29:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            30:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            31:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            32:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            33:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: /*
        !            36:  * Written by Paul Popelka (paulp@uts.amdahl.com)
        !            37:  *
        !            38:  * You can do anything you want with this software, just don't say you wrote
        !            39:  * it, and don't remove this notice.
        !            40:  *
        !            41:  * This software is provided "as is".
        !            42:  *
        !            43:  * The author supplies this software to be publicly redistributed on the
        !            44:  * understanding that the author is not responsible for the correct
        !            45:  * functioning of this software in any circumstances and is not liable for
        !            46:  * any damages caused by this software.
        !            47:  *
        !            48:  * October 1992
        !            49:  */
        !            50:
        !            51: #include <sys/param.h>
        !            52: #include <sys/systm.h>
        !            53: #include <sys/mount.h>
        !            54: #include <sys/malloc.h>
        !            55: #include <sys/proc.h>
        !            56: #include <sys/buf.h>
        !            57: #include <sys/vnode.h>
        !            58: #include <sys/kernel.h>                /* defines "time" */
        !            59: #include <sys/dirent.h>
        !            60: #include <sys/namei.h>
        !            61:
        !            62: #include <uvm/uvm_extern.h>
        !            63:
        !            64: #include <msdosfs/bpb.h>
        !            65: #include <msdosfs/msdosfsmount.h>
        !            66: #include <msdosfs/direntry.h>
        !            67: #include <msdosfs/denode.h>
        !            68: #include <msdosfs/fat.h>
        !            69:
        !            70: struct denode **dehashtbl;
        !            71: u_long dehash;                 /* size of hash table - 1 */
        !            72: #define        DEHASH(dev, dcl, doff)  (((dev) + (dcl) + (doff) / sizeof(struct direntry)) \
        !            73:                                 & dehash)
        !            74:
        !            75: static struct denode *msdosfs_hashget(dev_t, uint32_t, uint32_t);
        !            76: static int msdosfs_hashins(struct denode *);
        !            77: static void msdosfs_hashrem(struct denode *);
        !            78:
        !            79: /*ARGSUSED*/
        !            80: int
        !            81: msdosfs_init(vfsp)
        !            82:        struct vfsconf *vfsp;
        !            83: {
        !            84:        dehashtbl = hashinit(desiredvnodes/2, M_MSDOSFSMNT, M_WAITOK, &dehash);
        !            85:        return (0);
        !            86: }
        !            87:
        !            88: static struct denode *
        !            89: msdosfs_hashget(dev, dirclust, diroff)
        !            90:        dev_t dev;
        !            91:        uint32_t dirclust;
        !            92:        uint32_t diroff;
        !            93: {
        !            94:        struct denode *dep;
        !            95:        struct proc *p = curproc; /* XXX */
        !            96:
        !            97:        for (;;)
        !            98:                for (dep = dehashtbl[DEHASH(dev, dirclust, diroff)];;
        !            99:                     dep = dep->de_next) {
        !           100:                        if (dep == NULL)
        !           101:                                return (NULL);
        !           102:                        if (dirclust == dep->de_dirclust &&
        !           103:                            diroff == dep->de_diroffset &&
        !           104:                            dev == dep->de_dev &&
        !           105:                            dep->de_refcnt != 0) {
        !           106:                                struct vnode *vp = DETOV(dep);
        !           107:
        !           108:                                if (!vget(vp, LK_EXCLUSIVE, p))
        !           109:                                        return (dep);
        !           110:                                break;
        !           111:                        }
        !           112:                }
        !           113:        /* NOTREACHED */
        !           114: }
        !           115:
        !           116: static int
        !           117: msdosfs_hashins(dep)
        !           118:        struct denode *dep;
        !           119: {
        !           120:        struct denode **depp, *deq;
        !           121:
        !           122:        depp = &dehashtbl[DEHASH(dep->de_dev, dep->de_dirclust,
        !           123:                                 dep->de_diroffset)];
        !           124:
        !           125:        for (deq = *depp; deq; deq = deq->de_next) {
        !           126:                if (dep->de_dirclust == deq->de_dirclust &&
        !           127:                    dep->de_diroffset == deq->de_diroffset &&
        !           128:                    dep->de_dev == deq->de_dev &&
        !           129:                    deq->de_refcnt != 0) {
        !           130:                        return (EEXIST);
        !           131:                }
        !           132:        }
        !           133:
        !           134:        if ((deq = *depp) != NULL)
        !           135:                deq->de_prev = &dep->de_next;
        !           136:        dep->de_next = deq;
        !           137:        dep->de_prev = depp;
        !           138:        *depp = dep;
        !           139:        return (0);
        !           140: }
        !           141:
        !           142: static void
        !           143: msdosfs_hashrem(dep)
        !           144:        struct denode *dep;
        !           145: {
        !           146:        struct denode *deq;
        !           147:
        !           148:        if (dep->de_prev == NULL)
        !           149:                return;
        !           150:
        !           151:        if ((deq = dep->de_next) != NULL)
        !           152:                deq->de_prev = dep->de_prev;
        !           153:        *dep->de_prev = deq;
        !           154: #ifdef DIAGNOSTIC
        !           155:        dep->de_next = NULL;
        !           156:        dep->de_prev = NULL;
        !           157: #endif
        !           158: }
        !           159:
        !           160: /*
        !           161:  * If deget() succeeds it returns with the gotten denode locked().
        !           162:  *
        !           163:  * pmp      - address of msdosfsmount structure of the filesystem containing
        !           164:  *            the denode of interest.  The pm_dev field and the address of
        !           165:  *            the msdosfsmount structure are used.
        !           166:  * dirclust  - which cluster bp contains, if dirclust is 0 (root directory)
        !           167:  *            diroffset is relative to the beginning of the root directory,
        !           168:  *            otherwise it is cluster relative.
        !           169:  * diroffset - offset past begin of cluster of denode we want
        !           170:  * depp             - returns the address of the gotten denode.
        !           171:  */
        !           172: int
        !           173: deget(pmp, dirclust, diroffset, depp)
        !           174:        struct msdosfsmount *pmp;       /* so we know the maj/min number */
        !           175:        uint32_t dirclust;              /* cluster this dir entry came from */
        !           176:        uint32_t diroffset;             /* index of entry within the cluster */
        !           177:        struct denode **depp;           /* returns the addr of the gotten denode */
        !           178: {
        !           179:        int error;
        !           180:        extern int (**msdosfs_vnodeop_p)(void *);
        !           181:        struct direntry *direntptr;
        !           182:        struct denode *ldep;
        !           183:        struct vnode *nvp;
        !           184:        struct buf *bp;
        !           185:        struct proc *p = curproc; /* XXX */
        !           186:
        !           187: #ifdef MSDOSFS_DEBUG
        !           188:        printf("deget(pmp %08x, dirclust %d, diroffset %x, depp %08x)\n",
        !           189:            pmp, dirclust, diroffset, depp);
        !           190: #endif
        !           191:
        !           192:        /*
        !           193:         * On FAT32 filesystems, root is a (more or less) normal
        !           194:         * directory
        !           195:         */
        !           196:        if (FAT32(pmp) && dirclust == MSDOSFSROOT)
        !           197:                dirclust = pmp->pm_rootdirblk;
        !           198:
        !           199:        /*
        !           200:         * See if the denode is in the denode cache. Use the location of
        !           201:         * the directory entry to compute the hash value. For subdir use
        !           202:         * address of "." entry. For root dir (if not FAT32) use cluster
        !           203:         * MSDOSFSROOT, offset MSDOSFSROOT_OFS
        !           204:         *
        !           205:         * NOTE: The check for de_refcnt > 0 below insures the denode being
        !           206:         * examined does not represent an unlinked but still open file.
        !           207:         * These files are not to be accessible even when the directory
        !           208:         * entry that represented the file happens to be reused while the
        !           209:         * deleted file is still open.
        !           210:         */
        !           211: retry:
        !           212:        ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset);
        !           213:        if (ldep) {
        !           214:                *depp = ldep;
        !           215:                return (0);
        !           216:        }
        !           217:
        !           218:        /*
        !           219:         * Directory entry was not in cache, have to create a vnode and
        !           220:         * copy it from the passed disk buffer.
        !           221:         */
        !           222:        /* getnewvnode() does a VREF() on the vnode */
        !           223:        error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp,
        !           224:                            msdosfs_vnodeop_p, &nvp);
        !           225:        if (error) {
        !           226:                *depp = 0;
        !           227:                return (error);
        !           228:        }
        !           229:        MALLOC(ldep, struct denode *, sizeof(struct denode), M_MSDOSFSNODE,
        !           230:            M_WAITOK);
        !           231:        bzero((caddr_t)ldep, sizeof *ldep);
        !           232:        lockinit(&ldep->de_lock, PINOD, "denode", 0, 0);
        !           233:        nvp->v_data = ldep;
        !           234:        ldep->de_vnode = nvp;
        !           235:        ldep->de_flag = 0;
        !           236:        ldep->de_devvp = 0;
        !           237:        ldep->de_lockf = 0;
        !           238:        ldep->de_dev = pmp->pm_dev;
        !           239:        ldep->de_dirclust = dirclust;
        !           240:        ldep->de_diroffset = diroffset;
        !           241:        fc_purge(ldep, 0);      /* init the fat cache for this denode */
        !           242:
        !           243:        /*
        !           244:         * Insert the denode into the hash queue and lock the denode so it
        !           245:         * can't be accessed until we've read it in and have done what we
        !           246:         * need to it.
        !           247:         */
        !           248:        vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           249:        error = msdosfs_hashins(ldep);
        !           250:
        !           251:        if (error) {
        !           252:                vput (nvp);
        !           253:
        !           254:                if (error == EEXIST)
        !           255:                        goto retry;
        !           256:
        !           257:                return (error);
        !           258:        }
        !           259:
        !           260:        ldep->de_pmp = pmp;
        !           261:        ldep->de_devvp = pmp->pm_devvp;
        !           262:        ldep->de_refcnt = 1;
        !           263:        /*
        !           264:         * Copy the directory entry into the denode area of the vnode.
        !           265:         */
        !           266:        if ((dirclust == MSDOSFSROOT
        !           267:             || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
        !           268:            && diroffset == MSDOSFSROOT_OFS) {
        !           269:                /*
        !           270:                 * Directory entry for the root directory. There isn't one,
        !           271:                 * so we manufacture one. We should probably rummage
        !           272:                 * through the root directory and find a label entry (if it
        !           273:                 * exists), and then use the time and date from that entry
        !           274:                 * as the time and date for the root denode.
        !           275:                 */
        !           276:                nvp->v_flag |= VROOT; /* should be further down         XXX */
        !           277:
        !           278:                ldep->de_Attributes = ATTR_DIRECTORY;
        !           279:                if (FAT32(pmp))
        !           280:                        ldep->de_StartCluster = pmp->pm_rootdirblk;
        !           281:                        /* de_FileSize will be filled in further down */
        !           282:                else {
        !           283:                        ldep->de_StartCluster = MSDOSFSROOT;
        !           284:                        ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
        !           285:                }
        !           286:                /*
        !           287:                 * fill in time and date so that dos2unixtime() doesn't
        !           288:                 * spit up when called from msdosfs_getattr() with root
        !           289:                 * denode
        !           290:                 */
        !           291:                ldep->de_CTime = 0x0000;        /* 00:00:00      */
        !           292:                ldep->de_CTimeHundredth = 0;
        !           293:                ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
        !           294:                    | (1 << DD_DAY_SHIFT);
        !           295:                /* Jan 1, 1980   */
        !           296:                ldep->de_ADate = ldep->de_CDate;
        !           297:                ldep->de_MTime = ldep->de_CTime;
        !           298:                ldep->de_MDate = ldep->de_CDate;
        !           299:                /* leave the other fields as garbage */
        !           300:        } else {
        !           301:                error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
        !           302:                if (error)
        !           303:                        return (error);
        !           304:                DE_INTERNALIZE(ldep, direntptr);
        !           305:                brelse(bp);
        !           306:        }
        !           307:
        !           308:        /*
        !           309:         * Fill in a few fields of the vnode and finish filling in the
        !           310:         * denode.  Then return the address of the found denode.
        !           311:         */
        !           312:        if (ldep->de_Attributes & ATTR_DIRECTORY) {
        !           313:                /*
        !           314:                 * Since DOS directory entries that describe directories
        !           315:                 * have 0 in the filesize field, we take this opportunity
        !           316:                 * to find out the length of the directory and plug it into
        !           317:                 * the denode structure.
        !           318:                 */
        !           319:                uint32_t size;
        !           320:
        !           321:                nvp->v_type = VDIR;
        !           322:                if (ldep->de_StartCluster != MSDOSFSROOT) {
        !           323:                        error = pcbmap(ldep, 0xffff, 0, &size, 0);
        !           324:                        if (error == E2BIG) {
        !           325:                                ldep->de_FileSize = de_cn2off(pmp, size);
        !           326:                                error = 0;
        !           327:                        } else
        !           328:                                printf("deget(): pcbmap returned %d\n", error);
        !           329:                }
        !           330:        } else
        !           331:                nvp->v_type = VREG;
        !           332:        VREF(ldep->de_devvp);
        !           333:        *depp = ldep;
        !           334:        return (0);
        !           335: }
        !           336:
        !           337: int
        !           338: deupdat(dep, waitfor)
        !           339:        struct denode *dep;
        !           340:        int waitfor;
        !           341: {
        !           342:        struct buf *bp;
        !           343:        struct direntry *dirp;
        !           344:        int error;
        !           345:        struct timespec ts;
        !           346:
        !           347:        if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY)
        !           348:                return (0);
        !           349:        getnanotime(&ts);
        !           350:        DETIMES(dep, &ts, &ts, &ts);
        !           351:        if ((dep->de_flag & DE_MODIFIED) == 0)
        !           352:                return (0);
        !           353:        dep->de_flag &= ~DE_MODIFIED;
        !           354:        if (dep->de_Attributes & ATTR_DIRECTORY)
        !           355:                return (0);
        !           356:        if (dep->de_refcnt <= 0)
        !           357:                return (0);
        !           358:        error = readde(dep, &bp, &dirp);
        !           359:        if (error)
        !           360:                return (error);
        !           361:        DE_EXTERNALIZE(dirp, dep);
        !           362:        if (waitfor)
        !           363:                return (bwrite(bp));
        !           364:        else {
        !           365:                bdwrite(bp);
        !           366:                return (0);
        !           367:        }
        !           368: }
        !           369:
        !           370: /*
        !           371:  * Truncate the file described by dep to the length specified by length.
        !           372:  */
        !           373: int
        !           374: detrunc(dep, length, flags, cred, p)
        !           375:        struct denode *dep;
        !           376:        uint32_t length;
        !           377:        int flags;
        !           378:        struct ucred *cred;
        !           379:        struct proc *p;
        !           380: {
        !           381:        int error;
        !           382:        int allerror;
        !           383:        int vflags;
        !           384:        uint32_t eofentry;
        !           385:        uint32_t chaintofree;
        !           386:        daddr64_t bn;
        !           387:        int boff;
        !           388:        int isadir = dep->de_Attributes & ATTR_DIRECTORY;
        !           389:        struct buf *bp;
        !           390:        struct msdosfsmount *pmp = dep->de_pmp;
        !           391:
        !           392: #ifdef MSDOSFS_DEBUG
        !           393:        printf("detrunc(): file %s, length %ld, flags %d\n", dep->de_Name, length, flags);
        !           394: #endif
        !           395:
        !           396:        /*
        !           397:         * Disallow attempts to truncate the root directory since it is of
        !           398:         * fixed size.  That's just the way dos filesystems are.  We use
        !           399:         * the VROOT bit in the vnode because checking for the directory
        !           400:         * bit and a startcluster of 0 in the denode is not adequate to
        !           401:         * recognize the root directory at this point in a file or
        !           402:         * directory's life.
        !           403:         */
        !           404:        if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) {
        !           405:                printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n",
        !           406:                    dep->de_dirclust, dep->de_diroffset);
        !           407:                return (EINVAL);
        !           408:        }
        !           409:
        !           410:        uvm_vnp_setsize(DETOV(dep), length);
        !           411:
        !           412:        if (dep->de_FileSize < length)
        !           413:                return (deextend(dep, length, cred));
        !           414:
        !           415:        /*
        !           416:         * If the desired length is 0 then remember the starting cluster of
        !           417:         * the file and set the StartCluster field in the directory entry
        !           418:         * to 0.  If the desired length is not zero, then get the number of
        !           419:         * the last cluster in the shortened file.  Then get the number of
        !           420:         * the first cluster in the part of the file that is to be freed.
        !           421:         * Then set the next cluster pointer in the last cluster of the
        !           422:         * file to CLUST_EOFE.
        !           423:         */
        !           424:        if (length == 0) {
        !           425:                chaintofree = dep->de_StartCluster;
        !           426:                dep->de_StartCluster = 0;
        !           427:                eofentry = ~0;
        !           428:        } else {
        !           429:                error = pcbmap(dep, de_clcount(pmp, length) - 1, 0,
        !           430:                               &eofentry, 0);
        !           431:                if (error) {
        !           432: #ifdef MSDOSFS_DEBUG
        !           433:                        printf("detrunc(): pcbmap fails %d\n", error);
        !           434: #endif
        !           435:                        return (error);
        !           436:                }
        !           437:        }
        !           438:
        !           439:        fc_purge(dep, de_clcount(pmp, length));
        !           440:
        !           441:        /*
        !           442:         * If the new length is not a multiple of the cluster size then we
        !           443:         * must zero the tail end of the new last cluster in case it
        !           444:         * becomes part of the file again because of a seek.
        !           445:         */
        !           446:        if ((boff = length & pmp->pm_crbomask) != 0) {
        !           447:                if (isadir) {
        !           448:                        bn = cntobn(pmp, eofentry);
        !           449:                        error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster,
        !           450:                            NOCRED, &bp);
        !           451:                } else {
        !           452:                        bn = de_blk(pmp, length);
        !           453:                        error = bread(DETOV(dep), bn, pmp->pm_bpcluster,
        !           454:                            NOCRED, &bp);
        !           455:                }
        !           456:                if (error) {
        !           457:                        brelse(bp);
        !           458: #ifdef MSDOSFS_DEBUG
        !           459:                        printf("detrunc(): bread fails %d\n", error);
        !           460: #endif
        !           461:                        return (error);
        !           462:                }
        !           463:                uvm_vnp_uncache(DETOV(dep));
        !           464:                /*
        !           465:                 * is this the right place for it?
        !           466:                 */
        !           467:                bzero(bp->b_data + boff, pmp->pm_bpcluster - boff);
        !           468:                if (flags & IO_SYNC)
        !           469:                        bwrite(bp);
        !           470:                else
        !           471:                        bdwrite(bp);
        !           472:        }
        !           473:
        !           474:        /*
        !           475:         * Write out the updated directory entry.  Even if the update fails
        !           476:         * we free the trailing clusters.
        !           477:         */
        !           478:        dep->de_FileSize = length;
        !           479:        if (!isadir)
        !           480:                dep->de_flag |= DE_UPDATE|DE_MODIFIED;
        !           481:        vflags = (length > 0 ? V_SAVE : 0) | V_SAVEMETA;
        !           482:        vinvalbuf(DETOV(dep), vflags, cred, p, 0, 0);
        !           483:        allerror = deupdat(dep, 1);
        !           484: #ifdef MSDOSFS_DEBUG
        !           485:        printf("detrunc(): allerror %d, eofentry %d\n",
        !           486:               allerror, eofentry);
        !           487: #endif
        !           488:
        !           489:        /*
        !           490:         * If we need to break the cluster chain for the file then do it
        !           491:         * now.
        !           492:         */
        !           493:        if (eofentry != ~0) {
        !           494:                error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
        !           495:                                 &chaintofree, CLUST_EOFE);
        !           496:                if (error) {
        !           497: #ifdef MSDOSFS_DEBUG
        !           498:                        printf("detrunc(): fatentry errors %d\n", error);
        !           499: #endif
        !           500:                        return (error);
        !           501:                }
        !           502:                fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1),
        !           503:                            eofentry);
        !           504:        }
        !           505:
        !           506:        /*
        !           507:         * Now free the clusters removed from the file because of the
        !           508:         * truncation.
        !           509:         */
        !           510:        if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree))
        !           511:                freeclusterchain(pmp, chaintofree);
        !           512:
        !           513:        return (allerror);
        !           514: }
        !           515:
        !           516: /*
        !           517:  * Extend the file described by dep to length specified by length.
        !           518:  */
        !           519: int
        !           520: deextend(dep, length, cred)
        !           521:        struct denode *dep;
        !           522:        uint32_t length;
        !           523:        struct ucred *cred;
        !           524: {
        !           525:        struct msdosfsmount *pmp = dep->de_pmp;
        !           526:        uint32_t count;
        !           527:        int error;
        !           528:
        !           529:        /*
        !           530:         * The root of a DOS filesystem cannot be extended.
        !           531:         */
        !           532:        if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp))
        !           533:                return (EINVAL);
        !           534:
        !           535:        /*
        !           536:         * Directories cannot be extended.
        !           537:         */
        !           538:        if (dep->de_Attributes & ATTR_DIRECTORY)
        !           539:                return (EISDIR);
        !           540:
        !           541:        if (length <= dep->de_FileSize)
        !           542:                panic("deextend: file too large");
        !           543:
        !           544:        /*
        !           545:         * Compute the number of clusters to allocate.
        !           546:         */
        !           547:        count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
        !           548:        if (count > 0) {
        !           549:                if (count > pmp->pm_freeclustercount)
        !           550:                        return (ENOSPC);
        !           551:                error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
        !           552:                if (error) {
        !           553:                        /* truncate the added clusters away again */
        !           554:                        (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
        !           555:                        return (error);
        !           556:                }
        !           557:        }
        !           558:
        !           559:        dep->de_FileSize = length;
        !           560:        dep->de_flag |= DE_UPDATE|DE_MODIFIED;
        !           561:        return (deupdat(dep, 1));
        !           562: }
        !           563:
        !           564: /*
        !           565:  * Move a denode to its correct hash queue after the file it represents has
        !           566:  * been moved to a new directory.
        !           567:  */
        !           568: void
        !           569: reinsert(dep)
        !           570:        struct denode *dep;
        !           571: {
        !           572:        /*
        !           573:         * Fix up the denode cache.  If the denode is for a directory,
        !           574:         * there is nothing to do since the hash is based on the starting
        !           575:         * cluster of the directory file and that hasn't changed.  If for a
        !           576:         * file the hash is based on the location of the directory entry,
        !           577:         * so we must remove it from the cache and re-enter it with the
        !           578:         * hash based on the new location of the directory entry.
        !           579:         */
        !           580:        if (dep->de_Attributes & ATTR_DIRECTORY)
        !           581:                return;
        !           582:        msdosfs_hashrem(dep);
        !           583:        msdosfs_hashins(dep);
        !           584: }
        !           585:
        !           586: int
        !           587: msdosfs_reclaim(v)
        !           588:        void *v;
        !           589: {
        !           590:        struct vop_reclaim_args *ap = v;
        !           591:        struct vnode *vp = ap->a_vp;
        !           592:        struct denode *dep = VTODE(vp);
        !           593: #ifdef DIAGNOSTIC
        !           594:        extern int prtactive;
        !           595:
        !           596:        if (prtactive && vp->v_usecount != 0)
        !           597:                vprint("msdosfs_reclaim(): pushing active", vp);
        !           598: #endif
        !           599:
        !           600: #ifdef MSDOSFS_DEBUG
        !           601:        printf("msdosfs_reclaim(): dep %08x, file %s, refcnt %d\n",
        !           602:            dep, dep->de_Name, dep->de_refcnt);
        !           603: #endif
        !           604:
        !           605:        /*
        !           606:         * Remove the denode from its hash chain.
        !           607:         */
        !           608:        msdosfs_hashrem(dep);
        !           609:        /*
        !           610:         * Purge old data structures associated with the denode.
        !           611:         */
        !           612:        cache_purge(vp);
        !           613:        if (dep->de_devvp) {
        !           614:                vrele(dep->de_devvp);
        !           615:                dep->de_devvp = 0;
        !           616:        }
        !           617: #if 0 /* XXX */
        !           618:        dep->de_flag = 0;
        !           619: #endif
        !           620:        FREE(dep, M_MSDOSFSNODE);
        !           621:        vp->v_data = NULL;
        !           622:        return (0);
        !           623: }
        !           624:
        !           625: int
        !           626: msdosfs_inactive(v)
        !           627:        void *v;
        !           628: {
        !           629:        struct vop_inactive_args *ap = v;
        !           630:        struct vnode *vp = ap->a_vp;
        !           631:        struct denode *dep = VTODE(vp);
        !           632:        struct proc *p = ap->a_p;
        !           633:        int error;
        !           634: #ifdef DIAGNOSTIC
        !           635:        extern int prtactive;
        !           636:
        !           637:        if (prtactive && vp->v_usecount != 0)
        !           638:                vprint("msdosfs_inactive(): pushing active", vp);
        !           639: #endif
        !           640:
        !           641: #ifdef MSDOSFS_DEBUG
        !           642:        printf("msdosfs_inactive(): dep %08x, de_Name[0] %x\n", dep, dep->de_Name[0]);
        !           643: #endif
        !           644:
        !           645:        error = 0;
        !           646:
        !           647:        /*
        !           648:         * Get rid of denodes related to stale file handles.
        !           649:         */
        !           650:        if (dep->de_Name[0] == SLOT_DELETED)
        !           651:                goto out;
        !           652:
        !           653:        /*
        !           654:         * If the file has been deleted and it is on a read/write
        !           655:         * filesystem, then truncate the file, and mark the directory slot
        !           656:         * as empty.  (This may not be necessary for the dos filesystem.)
        !           657:         */
        !           658: #ifdef MSDOSFS_DEBUG
        !           659:        printf("msdosfs_inactive(): dep %08x, refcnt %d, mntflag %x, MNT_RDONLY %x\n",
        !           660:               dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
        !           661: #endif
        !           662:        if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
        !           663:                error = detrunc(dep, (uint32_t)0, 0, NOCRED, NULL);
        !           664:                dep->de_Name[0] = SLOT_DELETED;
        !           665:        }
        !           666:        deupdat(dep, 0);
        !           667:
        !           668: out:
        !           669:        VOP_UNLOCK(vp, 0, p);
        !           670:        /*
        !           671:         * If we are done with the denode, reclaim it
        !           672:         * so that it can be reused immediately.
        !           673:         */
        !           674: #ifdef MSDOSFS_DEBUG
        !           675:        printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
        !           676:               dep->de_Name[0]);
        !           677: #endif
        !           678:        if (dep->de_Name[0] == SLOT_DELETED)
        !           679:                vrecycle(vp, p);
        !           680:        return (error);
        !           681: }

CVSweb