[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

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