"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/coda-src/dir/dhcache.c" (26 Jun 2007, 6662 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 "dhcache.c" 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 #ifdef HAVE_CONFIG_H
   20 #include <config.h>
   21 #endif
   22 
   23 #include <sys/types.h>
   24 #include <sys/param.h>
   25 #include <unistd.h>
   26 #include "coda_string.h"
   27 
   28 #include <lwp/lwp.h>
   29 #include <lwp/lock.h>
   30 #include <dllist.h>
   31 #include <util.h>
   32 #include "codadir.h"
   33 
   34 /* this cache of directory handles is a child of the cvnode cache.
   35    For this reason we do not maintain a freelist.
   36 */
   37 /* directory handle cache entry */
   38 struct DCEntry {
   39     struct dllist_head    dc_hash;
   40     struct dllist_head    dc_list;
   41     int                   dc_count;/* number of VM vnodes referencing us */
   42     int                   dc_refcount; /* new refcount upon commit */
   43     struct DirHandle      dc_dh;
   44     PDirInode             dc_pdi;
   45     PDirInode             dc_cowpdi;
   46 };
   47 
   48 #define DCGROWTH 8
   49 #define DCSIZE 256
   50 #define DHLOGCACHESIZE 8
   51 
   52 static Lock               dlock;
   53 static struct dllist_head dcache[DCSIZE];
   54 static struct dllist_head dfreelist; 
   55 static struct dllist_head dnewlist; 
   56 
   57 
   58 static inline int  DC_Hash(PDirInode pdi) 
   59 {
   60     return ((int) ((unsigned long)pdi >> 5) % DCSIZE);
   61 }
   62 
   63 
   64 /* get more free entries in case freelist is empty */
   65 static void dc_Grow(int count)
   66 {
   67     PDCEntry pdce;
   68     int i;
   69 
   70     for ( i = 0 ; i < count ; i++ ) {
   71         pdce = malloc(sizeof(*pdce));
   72         CODA_ASSERT(pdce);
   73         memset(pdce, 0, sizeof(*pdce));
   74 
   75         list_head_init(&pdce->dc_hash);
   76         list_head_init(&pdce->dc_list);
   77 
   78         ObtainWriteLock(&dlock); 
   79         list_add(&pdce->dc_list, &dfreelist);
   80         ReleaseWriteLock(&dlock);
   81     }   
   82 }
   83 
   84 /* get a free cache entry; clean it up before handing it out */
   85 static PDCEntry dc_GetFree(void)
   86 {
   87     PDCEntry pdce = NULL;
   88 
   89  again:
   90     ObtainWriteLock(&dlock); 
   91     if ( !list_empty(&dfreelist) ) {
   92         pdce = list_entry(dfreelist.next, struct DCEntry, dc_list);
   93         list_del(&pdce->dc_list);
   94         list_del(&pdce->dc_hash);
   95 
   96         /* clean it up before use */
   97         if ( DH_Data(&pdce->dc_dh) )
   98             DH_FreeData(&pdce->dc_dh);
   99         memset(pdce, 0, sizeof(*pdce));
  100         list_head_init(&pdce->dc_list);
  101         list_head_init(&pdce->dc_hash);
  102         DH_Init(&pdce->dc_dh);
  103     }
  104     ReleaseWriteLock(&dlock);
  105     if ( pdce ) 
  106         return pdce;
  107 
  108     dc_Grow(DCGROWTH);
  109     goto again;
  110 }
  111 
  112 PDCEntry DC_Get(PDirInode pdi)
  113 {
  114     int hash;
  115     struct DCEntry *pdce;
  116     struct dllist_head *lh, *tmp;
  117     
  118     CODA_ASSERT(pdi);
  119     hash = DC_Hash(pdi);
  120 
  121     /* see if it is hashed already */
  122     ObtainWriteLock(&dlock); 
  123     lh = &dcache[hash]; 
  124     tmp = lh;
  125     while ( (tmp = tmp->next) != lh ) {
  126         pdce = list_entry(tmp, struct DCEntry, dc_hash);
  127         if ( pdi == pdce->dc_pdi ) {
  128             pdce->dc_count++;
  129             /* remove from freelist if first user */
  130             if ( pdce->dc_count == 1 ) {
  131                 list_del(&pdce->dc_list);
  132                 CODA_ASSERT(!DC_Dirty(pdce));
  133             }
  134 
  135             /* if data was flushed, refresh it */
  136             if ( !pdce->dc_dh.dh_data) {
  137                 pdce->dc_dh.dh_data = DI_DiToDh(pdi);
  138                 pdce->dc_refcount = pdi->di_refcount;
  139             }
  140 
  141             ReleaseWriteLock(&dlock);
  142             return pdce;
  143         }
  144     }
  145 
  146     /* release the lock since we are out of the hash table */
  147     ReleaseWriteLock(&dlock);
  148 
  149     /* not found use a new one */
  150     pdce = dc_GetFree();
  151     pdce->dc_count = 1;
  152     pdce->dc_pdi = pdi;
  153 
  154     /* re-lock since we want to mess with the lists again */
  155     ObtainWriteLock(&dlock); 
  156     list_add(&pdce->dc_hash, &dcache[hash]);
  157 
  158     /* copy in the directory handle, init lock, and copy data */
  159     pdce->dc_dh.dh_data = DI_DiToDh(pdi);
  160     CODA_ASSERT(!DC_Dirty(pdce));
  161     pdce->dc_refcount = pdi->di_refcount;
  162 
  163     ReleaseWriteLock(&dlock);
  164     return pdce;
  165 }
  166 
  167 
  168 
  169 /* Commit a DirInode - if new move it from the dnewlist to the hash list */
  170 /* called by VN_DCommit when the RVM Dir Inode for mkdir is created */
  171 void DC_Rehash(PDCEntry pdce)
  172 {
  173     int hash;
  174 
  175     CODA_ASSERT(pdce);
  176 
  177     hash = DC_Hash(pdce->dc_pdi);
  178 
  179     ObtainWriteLock(&dlock); 
  180 
  181     list_del(&pdce->dc_hash);
  182     list_add(&pdce->dc_hash, &dcache[hash]);
  183     ReleaseWriteLock(&dlock);
  184 }
  185 
  186 /* totally remove a cache entry & its data;
  187    careful - we are calling free! */
  188 void DC_Drop(PDCEntry pdce)
  189 {
  190     if ( pdce == NULL )
  191         return ;
  192     
  193     ObtainWriteLock(&dlock); 
  194     list_del(&pdce->dc_hash);
  195     list_del(&pdce->dc_list);
  196     ReleaseWriteLock(&dlock);
  197 
  198     DH_FreeData(&pdce->dc_dh);
  199     free(pdce);
  200 }
  201 
  202 void DC_HashInit(void)
  203 {
  204     int i;
  205 
  206     Lock_Init(&dlock);
  207 
  208     for ( i=0 ; i < DCSIZE ; i++ ) {
  209         list_head_init(&dcache[i]);
  210     }
  211     list_head_init(&dfreelist);
  212     list_head_init(&dnewlist);
  213 }
  214     
  215 
  216 void DC_Put(PDCEntry pdce)
  217 {
  218 
  219     ObtainWriteLock(&dlock); 
  220 
  221     if ( pdce->dc_count == 1 ) {
  222         list_add(&pdce->dc_list, dfreelist.prev);
  223         CODA_ASSERT(!DC_Dirty(pdce));
  224     } 
  225     pdce->dc_count--;
  226 
  227     ReleaseWriteLock(&dlock);
  228     return;
  229 }
  230 
  231 int DC_Count(PDCEntry pdce) 
  232 {
  233     return pdce->dc_count;
  234 }
  235 
  236 void DC_SetCount(PDCEntry pdce, int count) 
  237 {
  238     pdce->dc_count = count; 
  239 }
  240 
  241 
  242 
  243 /* called by ViceMakedir */
  244 PDCEntry DC_New(void)
  245 {
  246     PDCEntry pdce;
  247 
  248     pdce = dc_GetFree();
  249     pdce->dc_count = 1;
  250     pdce->dc_pdi = NULL;
  251     pdce->dc_refcount = 1;
  252     DC_SetDirty(pdce, 1);
  253 
  254     ObtainWriteLock(&dlock); 
  255     list_add(&pdce->dc_hash, &dnewlist);
  256     ReleaseWriteLock(&dlock);
  257 
  258     return pdce;
  259 }
  260 
  261 
  262 /* utility functions for setting/getting fields */
  263 inline int DC_Refcount(PDCEntry pdc)
  264 {
  265     return pdc->dc_refcount;
  266 }
  267 
  268 inline void DC_SetRefcount(PDCEntry pdc, int count)
  269 {
  270     pdc->dc_refcount = count;
  271 }
  272 
  273 PDirHandle DC_DC2DH(PDCEntry pdce)
  274 {
  275     CODA_ASSERT(pdce);
  276     return &pdce->dc_dh;
  277 }
  278 
  279 PDCEntry DC_DH2DC(PDirHandle pdh)
  280 {
  281     CODA_ASSERT(pdh);
  282     return list_entry(pdh, struct DCEntry, dc_dh);
  283 }
  284 
  285 
  286 PDirInode DC_DC2DI(PDCEntry pdce)
  287 {
  288     CODA_ASSERT(pdce);
  289     return pdce->dc_pdi;
  290 }
  291 
  292 void DC_SetDirh(PDCEntry pdce, PDirHeader pdh)
  293 {
  294     CODA_ASSERT(pdce);
  295     pdce->dc_dh.dh_data = pdh;
  296 }
  297 
  298 void DC_SetDI(PDCEntry pdce, PDirInode pdi)
  299 {
  300     CODA_ASSERT(pdce);
  301     pdce->dc_pdi = pdi;
  302 }
  303 
  304 
  305 void DC_SetCowpdi(PDCEntry pdce, PDirInode pdi)
  306 {
  307     CODA_ASSERT(pdce);
  308     pdce->dc_cowpdi = pdi;
  309     pdce->dc_pdi = NULL;
  310 }
  311 
  312 PDirInode DC_Cowpdi(PDCEntry pdce)
  313 {
  314     CODA_ASSERT(pdce);
  315     return pdce->dc_cowpdi;
  316 }
  317 
  318 
  319 void DC_SetDirty(PDCEntry pdce, int flag)
  320 {
  321     if ( !pdce ) 
  322         return;
  323     pdce->dc_dh.dh_dirty = flag;
  324 }
  325 
  326 int DC_Dirty(PDCEntry pdce)
  327 {
  328     CODA_ASSERT(pdce);
  329     return pdce->dc_dh.dh_dirty;
  330 }
  331         
  332 
  333 /* called by PutObjects to move the directory handle after copy on write */
  334 void DC_MoveDH(PDCEntry source, PDCEntry target)
  335 {
  336     target->dc_dh.dh_data = source->dc_dh.dh_data;
  337     source->dc_dh.dh_data = NULL;
  338 }
  339 
  340