"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/coda-src/vol/dirvnode.cc" (26 Jul 2006, 6712 Bytes) of package /linux/misc/old/coda-6.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dirvnode.cc" see the Fossies "Dox" file reference documentation.

    1 /* BLURB gpl
    2 
    3                            Coda File System
    4                               Release 6
    5 
    6           Copyright (c) 1987-2003 Carnegie Mellon University
    7                   Additional copyrights listed below
    8 
    9 This  code  is  distributed "AS IS" without warranty of any kind under
   10 the terms of the GNU General Public Licence Version 2, as shown in the
   11 file  LICENSE.  The  technical and financial  contributors to Coda are
   12 listed in the file CREDITS.
   13 
   14                         Additional copyrights
   15                            none currently
   16 
   17 #*/
   18 
   19 
   20 #ifdef __cplusplus
   21 extern "C" {
   22 #endif
   23 
   24 #ifdef HAVE_CONFIG_H
   25 #include <config.h>
   26 #endif
   27 
   28 #include <sys/types.h>
   29 #include <stdarg.h>
   30 #include <stdio.h>
   31 #include "coda_string.h"
   32 #include <unistd.h>
   33 #include <stdlib.h>
   34 
   35 #include <lwp/lwp.h>
   36 #include <lwp/lock.h>
   37 #include <util.h>
   38 #include <rvmlib.h>
   39 #include <codadir.h>
   40 #include <vice.h>
   41 #ifdef __cplusplus
   42 }
   43 #endif
   44 
   45 
   46 #include "cvnode.h"
   47 #include "volume.h"
   48 
   49 /* 
   50    This file manages the directory handle cache in conjunction 
   51    with Vnodes.
   52 
   53    The Directory Handle cache is controlled by the Vnode cache. 
   54    When directory content is needed, VN_SetDirHandle must be called. 
   55    When the Vnode goes away is calls DC_Drop to eliminate the cache.
   56    It could call DC_Put but presently the calls VN_SetDirHandle is not
   57    paired with a corresponding VN_PutDirHandle call. 
   58 
   59    The reference counting done by DC is therefore ignored:
   60    i.e. VN_SetDirHandle can be called at any time and need not te
   61    matched by equally many "Puts", when VN_PutDirHandle is called the
   62    cache entry will go away.
   63 
   64    This would be a good thing to fix, since it would potentially enhance 
   65    performance.
   66 
   67 */
   68 
   69 /* copies DirHandle data  into pages in recoverable storage */
   70 /* Called from within a transaction */
   71 int VN_DCommit(Vnode *vnp)
   72 {
   73     PDirInode pdi = vnp->disk.node.dirNode;
   74     PDCEntry  pdce = vnp->dh;
   75 
   76     if (!vnp || (vnp->disk.type != vDirectory) || !pdce) {
   77         DLog(29, "VN_DCommit: Vnode or dh not allocated/not a directory");
   78         return 0;
   79     }
   80 
   81     if (vnp->delete_me) {
   82         /* directory was deleted */
   83         DLog(29, "VN_DCommit: deleted directory, vnode = %x",
   84              vnp->vnodeNumber);
   85         vnp->disk.node.dirNode = NULL;
   86         /* if this vnode was just cloned, there won't be a pdi upon
   87            removal */
   88         if (pdi)
   89             DI_Dec(pdi);
   90     } else if (vnp->changed) {
   91         /* directory was modified - commit the pages */
   92         DLog(29, "VN_DCommit: Commiting pages for dir vnode = %x", 
   93             vnp->vnodeNumber);
   94         /* copy the VM pages into RVM */
   95         DI_DhToDi(pdce);
   96         /* CODA_ASSERT the directory inode now exists... */
   97         CODA_ASSERT(DC_DC2DI(pdce));
   98         /* rehash just in case it is new */
   99         DC_Rehash(pdce);
  100         vnp->disk.node.dirNode = DC_DC2DI(pdce);
  101     }
  102     return 0;
  103 }
  104 
  105 
  106 /* Eliminate the VM Data of the directory */
  107 int VN_DAbort(Vnode *vnp) 
  108 {
  109     
  110     if (!vnp || (vnp->disk.type != vDirectory) || !vnp->dh){
  111         DLog(29, "DAbort: Vnode not allocated, not a directory or no handle");
  112         return(0);
  113     }
  114     
  115     DH_FreeData(DC_DC2DH(vnp->dh));
  116     DC_SetDirty(vnp->dh, 0);
  117     
  118     /* if this was a new directory, clean up further */
  119     if ( !vnp->disk.node.dirNode ) {
  120         vnp->dh_refc = 0;
  121         DC_Drop(vnp->dh);
  122         vnp->dh = NULL;
  123     }
  124 
  125     return(0);
  126 }
  127 
  128 /* 
  129    this hashes the Directory Handle and copies inode pages into the DH. 
  130    dc_count exceeds the vn->dh_refc if a vnode clone exists in VM.
  131 */
  132 PDirHandle VN_SetDirHandle(struct Vnode *vn)
  133 {
  134     PDCEntry pdce = NULL;
  135 
  136     /* three cases:
  137        - new not previously seen: node.dirNode=0, dh=0
  138            - new, not yet in RVM: node.dirNode = 0, dh!=0
  139        - not new, already in RVM: node.dirNode != 0
  140     */
  141 
  142     if ( !vn->disk.node.dirNode && !vn->dh ) {
  143         pdce = DC_New();
  144         vn->dh = pdce;
  145         vn->dh_refc = 1;
  146         SLog(5, "VN_GetDirHandle NEW %x.%x: cnt %d\n",
  147              vn->vnodeNumber, vn->disk.uniquifier, DC_Count(pdce));
  148     } else if ( vn->disk.node.dirNode ) {
  149         pdce = DC_Get(vn->disk.node.dirNode);
  150         vn->dh = pdce;
  151         vn->dh_refc++;
  152         SLog(5, "VN_GetDirHandle for %x.%x: cnt %d, vn_cnt %d\n",
  153              vn->vnodeNumber, vn->disk.uniquifier, 
  154              DC_Count(pdce), vn->dh_refc);
  155     } else {
  156         pdce = vn->dh;
  157         DC_SetCount(pdce, DC_Count(pdce) + 1);
  158         vn->dh_refc++;
  159         SLog(5, "VN_GetDirHandle NEW-seen %x.%x: cnt %d, vn_ct %d\n",
  160              vn->vnodeNumber, vn->disk.uniquifier, 
  161              DC_Count(pdce), vn->dh_refc);
  162     }
  163 
  164     CODA_ASSERT( (vn->dh_refc>0) && (DC_Count(pdce)>=vn->dh_refc) );
  165     return DC_DC2DH(pdce);
  166 }
  167 
  168 /*
  169   VN_PutDirHandle: the Vnode is going away, clear the DC entry
  170  */
  171 void VN_PutDirHandle(struct Vnode *vn)
  172 {
  173     CODA_ASSERT(vn->dh);
  174 
  175     if (vn->dh) {
  176         SLog(5, "VN_PutDirHandle: %x.%x: cnt %d, vn_cnt %d\n",
  177              vn->vnodeNumber, vn->disk.uniquifier, 
  178              DC_Count(vn->dh)-1, vn->dh_refc-1);
  179         DC_Put(vn->dh);
  180         vn->dh_refc--;
  181         CODA_ASSERT(DC_Count(vn->dh) >= 0);
  182         if ( vn->dh_refc == 0 )
  183             vn->dh = 0;
  184     }
  185 }
  186 
  187 /* Drop DirHandle */
  188 void VN_DropDirHandle(struct Vnode *vn)
  189 {
  190     if (vn->dh) {
  191         SLog(5, "VN_DropDirHandle for %x.%x: cnt %d, vn_cnt %d\n",
  192              vn->vnodeNumber, vn->disk.uniquifier, DC_Count(vn->dh), vn->dh_refc);
  193         DC_Drop(vn->dh);
  194     }
  195     vn->dh_refc = 0;
  196     vn->dh = NULL;
  197 }
  198 
  199 /*
  200    - directories: set the disk.inode field to 0 and 
  201      create a dcentry with the _old_ contents. 
  202    NOTES:
  203    - afterwards the vptr->dh  will have VM data, 
  204      but no RVM data.
  205    - the reference counts of the vnode and the cache entries
  206      are split appropriately.
  207 
  208 */
  209 void VN_CopyOnWrite(struct Vnode *vn)
  210 {
  211     PDCEntry pdce;
  212     PDCEntry oldpdce;
  213     PDirHeader pdirh;
  214     PDirHandle pdh;
  215     int others_count;
  216 
  217     CODA_ASSERT(vn->disk.node.dirNode);
  218     /* pin it */
  219     pdh = VN_SetDirHandle(vn);
  220     CODA_ASSERT(pdh);
  221     oldpdce = DC_DH2DC(pdh);
  222     others_count = DC_Count(oldpdce) - vn->dh_refc;
  223 
  224     /* no one else has a reference to this directory - 
  225        merely prepare for cloning the RVM directory inode */
  226     if ( ! others_count ) {
  227         DC_SetCowpdi(oldpdce, vn->disk.node.dirNode);
  228         DC_SetRefcount(oldpdce, 1);
  229         DC_SetDirty(oldpdce, 1);
  230     }
  231 
  232     /* other vnodes have a reference to this directory -
  233        prepare for cloning the RVM directory inode _and_
  234        clone the VM directory cache entry now */
  235     if ( others_count ) {
  236         pdce= DC_New();
  237         CODA_ASSERT(pdce);
  238 
  239         /* get pointer to VM data */
  240         pdirh = (PDirHeader) malloc(DH_Length(pdh));
  241         CODA_ASSERT(pdirh);
  242         memcpy(pdirh, DH_Data(pdh), DH_Length(pdh));
  243         
  244         /* set up the copied directory */
  245         vn->dh = pdce;
  246         DC_SetDirh(pdce, pdirh);
  247         DC_SetCowpdi(pdce, vn->disk.node.dirNode);
  248         DC_SetDirty(pdce, 1);
  249         DC_SetCount(pdce, vn->dh_refc);
  250 
  251         /* subtract our references to the oldpdce */
  252         DC_SetCount(oldpdce, others_count);
  253     }
  254 
  255     vn->disk.node.dirNode = NULL;
  256     vn->disk.cloned = 0;
  257     VN_PutDirHandle(vn);
  258     
  259     SLog(5, "VN_CopyOnWrite: New other_count: %d dh_refc %d", 
  260          others_count, vn->dh_refc);
  261 }