The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/msdosfs/msdosfs_denode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD$ */
    2 /*      $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg 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/kernel.h>
   54 #include <sys/mount.h>
   55 #include <sys/malloc.h>
   56 #include <sys/proc.h>
   57 #include <sys/buf.h>
   58 #include <sys/vnode.h>
   59 
   60 #include <vm/vm.h>
   61 #include <vm/vm_extern.h>
   62 
   63 #include <msdosfs/bpb.h>
   64 #include <msdosfs/msdosfsmount.h>
   65 #include <msdosfs/direntry.h>
   66 #include <msdosfs/denode.h>
   67 #include <msdosfs/fat.h>
   68 
   69 static MALLOC_DEFINE(M_MSDOSFSNODE, "MSDOSFS node", "MSDOSFS vnode private part");
   70 
   71 static struct denode **dehashtbl;
   72 static u_long dehash;                   /* size of hash table - 1 */
   73 #define DEHASH(dev, dcl, doff)  (dehashtbl[((dev) + (dcl) + (doff) /    \
   74                                 sizeof(struct direntry)) & dehash])
   75 #ifndef NULL_SIMPLELOCKS
   76 static struct simplelock dehash_slock;
   77 #endif
   78 
   79 union _qcvt {
   80         quad_t qcvt;
   81         long val[2];
   82 };
   83 #define SETHIGH(q, h) { \
   84         union _qcvt tmp; \
   85         tmp.qcvt = (q); \
   86         tmp.val[_QUAD_HIGHWORD] = (h); \
   87         (q) = tmp.qcvt; \
   88 }
   89 #define SETLOW(q, l) { \
   90         union _qcvt tmp; \
   91         tmp.qcvt = (q); \
   92         tmp.val[_QUAD_LOWWORD] = (l); \
   93         (q) = tmp.qcvt; \
   94 }
   95 
   96 static struct denode *
   97                 msdosfs_hashget __P((dev_t dev, u_long dirclust,
   98                                      u_long diroff));
   99 static void     msdosfs_hashins __P((struct denode *dep));
  100 static void     msdosfs_hashrem __P((struct denode *dep));
  101 
  102 /*ARGSUSED*/
  103 int 
  104 msdosfs_init(vfsp)
  105         struct vfsconf *vfsp;
  106 {
  107         dehashtbl = hashinit(desiredvnodes/2, M_MSDOSFSMNT, &dehash);
  108         simple_lock_init(&dehash_slock);
  109         return (0);
  110 }
  111 
  112 static struct denode *
  113 msdosfs_hashget(dev, dirclust, diroff)
  114         dev_t dev;
  115         u_long dirclust;
  116         u_long diroff;
  117 {
  118         struct proc *p = curproc;       /* XXX */
  119         struct denode *dep;
  120         struct vnode *vp;
  121 
  122 loop:
  123         simple_lock(&dehash_slock);
  124         for (dep = DEHASH(dev, dirclust, diroff); dep; dep = dep->de_next) {
  125                 if (dirclust == dep->de_dirclust
  126                     && diroff == dep->de_diroffset
  127                     && dev == dep->de_dev
  128                     && dep->de_refcnt != 0) {
  129                         vp = DETOV(dep);
  130                         simple_lock(&vp->v_interlock);
  131                         simple_unlock(&dehash_slock);
  132                         if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
  133                                 goto loop;
  134                         return (dep);
  135                 }
  136         }
  137         simple_unlock(&dehash_slock);
  138         return (NULL);
  139 }
  140 
  141 static void
  142 msdosfs_hashins(dep)
  143         struct denode *dep;
  144 {
  145         struct denode **depp, *deq;
  146 
  147         simple_lock(&dehash_slock);
  148         depp = &DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset);
  149         deq = *depp;
  150         if (deq)
  151                 deq->de_prev = &dep->de_next;
  152         dep->de_next = deq;
  153         dep->de_prev = depp;
  154         *depp = dep;
  155         simple_unlock(&dehash_slock);
  156 }
  157 
  158 static void
  159 msdosfs_hashrem(dep)
  160         struct denode *dep;
  161 {
  162         struct denode *deq;
  163 
  164         simple_lock(&dehash_slock);
  165         deq = dep->de_next;
  166         if (deq)
  167                 deq->de_prev = dep->de_prev;
  168         *dep->de_prev = deq;
  169 #ifdef DIAGNOSTIC
  170         dep->de_next = NULL;
  171         dep->de_prev = NULL;
  172 #endif
  173         simple_unlock(&dehash_slock);
  174 }
  175 
  176 /*
  177  * If deget() succeeds it returns with the gotten denode locked().
  178  *
  179  * pmp       - address of msdosfsmount structure of the filesystem containing
  180  *             the denode of interest.  The pm_dev field and the address of
  181  *             the msdosfsmount structure are used.
  182  * dirclust  - which cluster bp contains, if dirclust is 0 (root directory)
  183  *             diroffset is relative to the beginning of the root directory,
  184  *             otherwise it is cluster relative.
  185  * diroffset - offset past begin of cluster of denode we want
  186  * depp      - returns the address of the gotten denode.
  187  */
  188 int
  189 deget(pmp, dirclust, diroffset, depp)
  190         struct msdosfsmount *pmp;       /* so we know the maj/min number */
  191         u_long dirclust;                /* cluster this dir entry came from */
  192         u_long diroffset;               /* index of entry within the cluster */
  193         struct denode **depp;           /* returns the addr of the gotten denode */
  194 {
  195         int error;
  196         dev_t dev = pmp->pm_dev;
  197         struct mount *mntp = pmp->pm_mountp;
  198         struct direntry *direntptr;
  199         struct denode *ldep;
  200         struct vnode *nvp;
  201         struct buf *bp;
  202         struct proc *p = curproc;       /* XXX */
  203         struct timeval tv;
  204 
  205 #ifdef MSDOSFS_DEBUG
  206         printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
  207             pmp, dirclust, diroffset, depp);
  208 #endif
  209 
  210         /*
  211          * On FAT32 filesystems, root is a (more or less) normal
  212          * directory
  213          */
  214         if (FAT32(pmp) && dirclust == MSDOSFSROOT)
  215                 dirclust = pmp->pm_rootdirblk;
  216 
  217         /*
  218          * See if the denode is in the denode cache. Use the location of
  219          * the directory entry to compute the hash value. For subdir use
  220          * address of "." entry. For root dir (if not FAT32) use cluster
  221          * MSDOSFSROOT, offset MSDOSFSROOT_OFS
  222          *
  223          * NOTE: The check for de_refcnt > 0 below insures the denode being
  224          * examined does not represent an unlinked but still open file.
  225          * These files are not to be accessible even when the directory
  226          * entry that represented the file happens to be reused while the
  227          * deleted file is still open.
  228          */
  229         ldep = msdosfs_hashget(dev, dirclust, diroffset);
  230         if (ldep) {
  231                 *depp = ldep;
  232                 return (0);
  233         }
  234 
  235         /*
  236          * Do the MALLOC before the getnewvnode since doing so afterward
  237          * might cause a bogus v_data pointer to get dereferenced
  238          * elsewhere if MALLOC should block.
  239          */
  240         MALLOC(ldep, struct denode *, sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK);
  241 
  242         /*
  243          * Directory entry was not in cache, have to create a vnode and
  244          * copy it from the passed disk buffer.
  245          */
  246         /* getnewvnode() does a VREF() on the vnode */
  247         error = getnewvnode(VT_MSDOSFS, mntp, msdosfs_vnodeop_p, &nvp);
  248         if (error) {
  249                 *depp = NULL;
  250                 FREE(ldep, M_MSDOSFSNODE);
  251                 return error;
  252         }
  253         bzero((caddr_t)ldep, sizeof *ldep);
  254         lockinit(&ldep->de_lock, PINOD, "denode", 0, 0);
  255         nvp->v_data = ldep;
  256         ldep->de_vnode = nvp;
  257         ldep->de_flag = 0;
  258         ldep->de_devvp = 0;
  259         ldep->de_dev = dev;
  260         ldep->de_dirclust = dirclust;
  261         ldep->de_diroffset = diroffset;
  262         fc_purge(ldep, 0);      /* init the fat cache for this denode */
  263 
  264         /*
  265          * Lock the denode so that it can't be accessed until we've read
  266          * it in and have done what we need to it.  Do this here instead
  267          * of at the start of msdosfs_hashins() so that reinsert() can
  268          * call msdosfs_hashins() with a locked denode.
  269          */
  270         if (lockmgr(&ldep->de_lock, LK_EXCLUSIVE, (struct simplelock *)0, p))
  271                 panic("deget: unexpected lock failure");
  272 
  273         /*
  274          * Insert the denode into the hash queue.
  275          */
  276         msdosfs_hashins(ldep);
  277 
  278         ldep->de_pmp = pmp;
  279         ldep->de_refcnt = 1;
  280         /*
  281          * Copy the directory entry into the denode area of the vnode.
  282          */
  283         if ((dirclust == MSDOSFSROOT
  284              || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
  285             && diroffset == MSDOSFSROOT_OFS) {
  286                 /*
  287                  * Directory entry for the root directory. There isn't one,
  288                  * so we manufacture one. We should probably rummage
  289                  * through the root directory and find a label entry (if it
  290                  * exists), and then use the time and date from that entry
  291                  * as the time and date for the root denode.
  292                  */
  293                 nvp->v_flag |= VROOT; /* should be further down         XXX */
  294 
  295                 ldep->de_Attributes = ATTR_DIRECTORY;
  296                 ldep->de_LowerCase = 0;
  297                 if (FAT32(pmp))
  298                         ldep->de_StartCluster = pmp->pm_rootdirblk;
  299                         /* de_FileSize will be filled in further down */
  300                 else {
  301                         ldep->de_StartCluster = MSDOSFSROOT;
  302                         ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE;
  303                 }
  304                 /*
  305                  * fill in time and date so that dos2unixtime() doesn't
  306                  * spit up when called from msdosfs_getattr() with root
  307                  * denode
  308                  */
  309                 ldep->de_CHun = 0;
  310                 ldep->de_CTime = 0x0000;        /* 00:00:00      */
  311                 ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
  312                     | (1 << DD_DAY_SHIFT);
  313                 /* Jan 1, 1980   */
  314                 ldep->de_ADate = ldep->de_CDate;
  315                 ldep->de_MTime = ldep->de_CTime;
  316                 ldep->de_MDate = ldep->de_CDate;
  317                 /* leave the other fields as garbage */
  318         } else {
  319                 error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
  320                 if (error) {
  321                         /*
  322                          * The denode does not contain anything useful, so
  323                          * it would be wrong to leave it on its hash chain.
  324                          * Arrange for vput() to just forget about it.
  325                          */
  326                         ldep->de_Name[0] = SLOT_DELETED;
  327 
  328                         vput(nvp);
  329                         *depp = NULL;
  330                         return (error);
  331                 }
  332                 DE_INTERNALIZE(ldep, direntptr);
  333                 brelse(bp);
  334         }
  335 
  336         /*
  337          * Fill in a few fields of the vnode and finish filling in the
  338          * denode.  Then return the address of the found denode.
  339          */
  340         if (ldep->de_Attributes & ATTR_DIRECTORY) {
  341                 /*
  342                  * Since DOS directory entries that describe directories
  343                  * have 0 in the filesize field, we take this opportunity
  344                  * to find out the length of the directory and plug it into
  345                  * the denode structure.
  346                  */
  347                 u_long size;
  348 
  349                 nvp->v_type = VDIR;
  350                 if (ldep->de_StartCluster != MSDOSFSROOT) {
  351                         error = pcbmap(ldep, 0xffff, 0, &size, 0);
  352                         if (error == E2BIG) {
  353                                 ldep->de_FileSize = de_cn2off(pmp, size);
  354                                 error = 0;
  355                         } else
  356                                 printf("deget(): pcbmap returned %d\n", error);
  357                 }
  358         } else
  359                 nvp->v_type = VREG;
  360         getmicrouptime(&tv);
  361         SETHIGH(ldep->de_modrev, tv.tv_sec);
  362         SETLOW(ldep->de_modrev, tv.tv_usec * 4294);
  363         ldep->de_devvp = pmp->pm_devvp;
  364         VREF(ldep->de_devvp);
  365         *depp = ldep;
  366         return (0);
  367 }
  368 
  369 int
  370 deupdat(dep, waitfor)
  371         struct denode *dep;
  372         int waitfor;
  373 {
  374         int error;
  375         struct buf *bp;
  376         struct direntry *dirp;
  377         struct timespec ts;
  378 
  379         if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY)
  380                 return (0);
  381         getnanotime(&ts);
  382         DETIMES(dep, &ts, &ts, &ts);
  383         if ((dep->de_flag & DE_MODIFIED) == 0)
  384                 return (0);
  385         dep->de_flag &= ~DE_MODIFIED;
  386         if (dep->de_Attributes & ATTR_DIRECTORY)
  387                 return (0);
  388         if (dep->de_refcnt <= 0)
  389                 return (0);
  390         error = readde(dep, &bp, &dirp);
  391         if (error)
  392                 return (error);
  393         DE_EXTERNALIZE(dirp, dep);
  394         if (waitfor)
  395                 return (bwrite(bp));
  396         else {
  397                 bdwrite(bp);
  398                 return (0);
  399         }
  400 }
  401 
  402 /*
  403  * Truncate the file described by dep to the length specified by length.
  404  */
  405 int
  406 detrunc(dep, length, flags, cred, p)
  407         struct denode *dep;
  408         u_long length;
  409         int flags;
  410         struct ucred *cred;
  411         struct proc *p;
  412 {
  413         int error;
  414         int allerror;
  415         u_long eofentry;
  416         u_long chaintofree;
  417         daddr_t bn;
  418         int boff;
  419         int isadir = dep->de_Attributes & ATTR_DIRECTORY;
  420         struct buf *bp;
  421         struct msdosfsmount *pmp = dep->de_pmp;
  422 
  423 #ifdef MSDOSFS_DEBUG
  424         printf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, length, flags);
  425 #endif
  426 
  427         /*
  428          * Disallow attempts to truncate the root directory since it is of
  429          * fixed size.  That's just the way dos filesystems are.  We use
  430          * the VROOT bit in the vnode because checking for the directory
  431          * bit and a startcluster of 0 in the denode is not adequate to
  432          * recognize the root directory at this point in a file or
  433          * directory's life.
  434          */
  435         if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) {
  436                 printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n",
  437                     dep->de_dirclust, dep->de_diroffset);
  438                 return (EINVAL);
  439         }
  440 
  441 
  442         if (dep->de_FileSize < length) {
  443                 vnode_pager_setsize(DETOV(dep), length);
  444                 return deextend(dep, length, cred);
  445         }
  446 
  447         /*
  448          * If the desired length is 0 then remember the starting cluster of
  449          * the file and set the StartCluster field in the directory entry
  450          * to 0.  If the desired length is not zero, then get the number of
  451          * the last cluster in the shortened file.  Then get the number of
  452          * the first cluster in the part of the file that is to be freed.
  453          * Then set the next cluster pointer in the last cluster of the
  454          * file to CLUST_EOFE.
  455          */
  456         if (length == 0) {
  457                 chaintofree = dep->de_StartCluster;
  458                 dep->de_StartCluster = 0;
  459                 eofentry = ~0;
  460         } else {
  461                 error = pcbmap(dep, de_clcount(pmp, length) - 1, 0, 
  462                                &eofentry, 0);
  463                 if (error) {
  464 #ifdef MSDOSFS_DEBUG
  465                         printf("detrunc(): pcbmap fails %d\n", error);
  466 #endif
  467                         return (error);
  468                 }
  469         }
  470 
  471         fc_purge(dep, de_clcount(pmp, length));
  472 
  473         /*
  474          * If the new length is not a multiple of the cluster size then we
  475          * must zero the tail end of the new last cluster in case it
  476          * becomes part of the file again because of a seek.
  477          */
  478         if ((boff = length & pmp->pm_crbomask) != 0) {
  479                 if (isadir) {
  480                         bn = cntobn(pmp, eofentry);
  481                         error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster,
  482                             NOCRED, &bp);
  483                 } else {
  484                         bn = de_blk(pmp, length);
  485                         error = bread(DETOV(dep), bn, pmp->pm_bpcluster,
  486                             NOCRED, &bp);
  487                 }
  488                 if (error) {
  489                         brelse(bp);
  490 #ifdef MSDOSFS_DEBUG
  491                         printf("detrunc(): bread fails %d\n", error);
  492 #endif
  493                         return (error);
  494                 }
  495                 /*
  496                  * is this the right place for it?
  497                  */
  498                 bzero(bp->b_data + boff, pmp->pm_bpcluster - boff);
  499                 if (flags & IO_SYNC)
  500                         bwrite(bp);
  501                 else
  502                         bdwrite(bp);
  503         }
  504 
  505         /*
  506          * Write out the updated directory entry.  Even if the update fails
  507          * we free the trailing clusters.
  508          */
  509         dep->de_FileSize = length;
  510         if (!isadir)
  511                 dep->de_flag |= DE_UPDATE|DE_MODIFIED;
  512         allerror = vtruncbuf(DETOV(dep), cred, p, length, pmp->pm_bpcluster);
  513 #ifdef MSDOSFS_DEBUG
  514         if (allerror)
  515                 printf("detrunc(): vtruncbuf error %d\n", allerror);
  516 #endif
  517         error = deupdat(dep, 1);
  518         if (error && (allerror == 0))
  519                 allerror = error;
  520 #ifdef MSDOSFS_DEBUG
  521         printf("detrunc(): allerror %d, eofentry %lu\n",
  522                allerror, eofentry);
  523 #endif
  524 
  525         /*
  526          * If we need to break the cluster chain for the file then do it
  527          * now.
  528          */
  529         if (eofentry != ~0) {
  530                 error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
  531                                  &chaintofree, CLUST_EOFE);
  532                 if (error) {
  533 #ifdef MSDOSFS_DEBUG
  534                         printf("detrunc(): fatentry errors %d\n", error);
  535 #endif
  536                         return (error);
  537                 }
  538                 fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1),
  539                             eofentry);
  540         }
  541 
  542         /*
  543          * Now free the clusters removed from the file because of the
  544          * truncation.
  545          */
  546         if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree))
  547                 freeclusterchain(pmp, chaintofree);
  548 
  549         return (allerror);
  550 }
  551 
  552 /*
  553  * Extend the file described by dep to length specified by length.
  554  */
  555 int
  556 deextend(dep, length, cred)
  557         struct denode *dep;
  558         u_long length;
  559         struct ucred *cred;
  560 {
  561         struct msdosfsmount *pmp = dep->de_pmp;
  562         u_long count;
  563         int error;
  564 
  565         /*
  566          * The root of a DOS filesystem cannot be extended.
  567          */
  568         if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp))
  569                 return (EINVAL);
  570 
  571         /*
  572          * Directories cannot be extended.
  573          */
  574         if (dep->de_Attributes & ATTR_DIRECTORY)
  575                 return (EISDIR);
  576 
  577         if (length <= dep->de_FileSize)
  578                 panic("deextend: file too large");
  579 
  580         /*
  581          * Compute the number of clusters to allocate.
  582          */
  583         count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
  584         if (count > 0) {
  585                 if (count > pmp->pm_freeclustercount)
  586                         return (ENOSPC);
  587                 error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
  588                 if (error) {
  589                         /* truncate the added clusters away again */
  590                         (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
  591                         return (error);
  592                 }
  593         }
  594         dep->de_FileSize = length;
  595         dep->de_flag |= DE_UPDATE|DE_MODIFIED;
  596         return (deupdat(dep, 1));
  597 }
  598 
  599 /*
  600  * Move a denode to its correct hash queue after the file it represents has
  601  * been moved to a new directory.
  602  */
  603 void
  604 reinsert(dep)
  605         struct denode *dep;
  606 {
  607         /*
  608          * Fix up the denode cache.  If the denode is for a directory,
  609          * there is nothing to do since the hash is based on the starting
  610          * cluster of the directory file and that hasn't changed.  If for a
  611          * file the hash is based on the location of the directory entry,
  612          * so we must remove it from the cache and re-enter it with the
  613          * hash based on the new location of the directory entry.
  614          */
  615         if (dep->de_Attributes & ATTR_DIRECTORY)
  616                 return;
  617         msdosfs_hashrem(dep);
  618         msdosfs_hashins(dep);
  619 }
  620 
  621 int
  622 msdosfs_reclaim(ap)
  623         struct vop_reclaim_args /* {
  624                 struct vnode *a_vp;
  625         } */ *ap;
  626 {
  627         struct vnode *vp = ap->a_vp;
  628         struct denode *dep = VTODE(vp);
  629 
  630 #ifdef MSDOSFS_DEBUG
  631         printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n",
  632             dep, dep->de_Name, dep->de_refcnt);
  633 #endif
  634 
  635         if (prtactive && vp->v_usecount != 0)
  636                 vprint("msdosfs_reclaim(): pushing active", vp);
  637         /*
  638          * Remove the denode from its hash chain.
  639          */
  640         msdosfs_hashrem(dep);
  641         /*
  642          * Purge old data structures associated with the denode.
  643          */
  644         cache_purge(vp);
  645         if (dep->de_devvp) {
  646                 vrele(dep->de_devvp);
  647                 dep->de_devvp = 0;
  648         }
  649 #if 0 /* XXX */
  650         dep->de_flag = 0;
  651 #endif
  652         FREE(dep, M_MSDOSFSNODE);
  653         vp->v_data = NULL;
  654 
  655         return (0);
  656 }
  657 
  658 int
  659 msdosfs_inactive(ap)
  660         struct vop_inactive_args /* {
  661                 struct vnode *a_vp;
  662                 struct proc *a_p;
  663         } */ *ap;
  664 {
  665         struct vnode *vp = ap->a_vp;
  666         struct denode *dep = VTODE(vp);
  667         struct proc *p = ap->a_p;
  668         int error = 0;
  669 
  670 #ifdef MSDOSFS_DEBUG
  671         printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
  672 #endif
  673 
  674         if (prtactive && vp->v_usecount != 0)
  675                 vprint("msdosfs_inactive(): pushing active", vp);
  676 
  677         /*
  678          * Ignore denodes related to stale file handles.
  679          */
  680         if (dep->de_Name[0] == SLOT_DELETED)
  681                 goto out;
  682 
  683         /*
  684          * If the file has been deleted and it is on a read/write
  685          * filesystem, then truncate the file, and mark the directory slot
  686          * as empty.  (This may not be necessary for the dos filesystem.)
  687          */
  688 #ifdef MSDOSFS_DEBUG
  689         printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
  690                dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
  691 #endif
  692         if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
  693                 error = detrunc(dep, (u_long) 0, 0, NOCRED, p);
  694                 dep->de_flag |= DE_UPDATE;
  695                 dep->de_Name[0] = SLOT_DELETED;
  696         }
  697         deupdat(dep, 0);
  698 
  699 out:
  700         VOP_UNLOCK(vp, 0, p);
  701         /*
  702          * If we are done with the denode, reclaim it
  703          * so that it can be reused immediately.
  704          */
  705 #ifdef MSDOSFS_DEBUG
  706         printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
  707                dep->de_Name[0]);
  708 #endif
  709         if (dep->de_Name[0] == SLOT_DELETED)
  710                 vrecycle(vp, (struct simplelock *)0, p);
  711         return (error);
  712 }

Cache object: a5adf8b39a6413e69ea49ddfa547fbf6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.