/[hurd]/hurd/ext2fs/pager.c
ViewVC logotype

Diff of /hurd/ext2fs/pager.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.74 by marcus, Tue Jul 12 15:29:22 2005 UTC revision 1.74.2.1 by ams, Thu Aug 25 18:34:18 2005 UTC
# Line 1  Line 1 
1  /* Pager for ext2fs  /* Pager for ext2fs
2    
3     Copyright (C) 1994,95,96,97,98,99,2000,02 Free Software Foundation, Inc.     Copyright (C) 1994,95,96,97,98,99,2000,02,05 Free Software Foundation, Inc.
4    
5     Converted for ext2fs by Miles Bader <miles@gnu.org>     Converted for ext2fs by Miles Bader <miles@gnu.org>
6    
# Line 18  Line 18 
18     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20    
21    #include <unistd.h>
22  #include <string.h>  #include <string.h>
23  #include <errno.h>  #include <errno.h>
24  #include <hurd/store.h>  #include <hurd/store.h>
25  #include "ext2fs.h"  #include "ext2fs.h"
26    
27    /* XXX */
28    #include "../libpager/priv.h"
29    
30  /* A ports bucket to hold pager ports.  */  /* A ports bucket to hold pager ports.  */
31  struct port_bucket *pager_bucket;  struct port_bucket *pager_bucket;
32    
 /* Mapped image of the disk.  */  
 void *disk_image;  
   
33  spin_lock_t node_to_page_lock = SPIN_LOCK_INITIALIZER;  spin_lock_t node_to_page_lock = SPIN_LOCK_INITIALIZER;
34    
35  #ifdef DONT_CACHE_MEMORY_OBJECTS  #ifdef DONT_CACHE_MEMORY_OBJECTS
# Line 163  file_pager_read_page (struct node *node, Line 164  file_pager_read_page (struct node *node,
164    block_t pending_blocks = 0;    block_t pending_blocks = 0;
165    int num_pending_blocks = 0;    int num_pending_blocks = 0;
166    
167      ext2_debug ("reading inode %Ld page %u[%d]",
168                  node->cache_id, page, vm_page_size);
169    
170    /* Read the NUM_PENDING_BLOCKS blocks in PENDING_BLOCKS, into the buffer    /* Read the NUM_PENDING_BLOCKS blocks in PENDING_BLOCKS, into the buffer
171       pointed to by BUF (allocating it if necessary) at offset OFFS.  OFFS in       pointed to by BUF (allocating it if necessary) at offset OFFS.  OFFS in
172       adjusted by the amount read, and NUM_PENDING_BLOCKS is zeroed.  Any read       adjusted by the amount read, and NUM_PENDING_BLOCKS is zeroed.  Any read
# Line 171  file_pager_read_page (struct node *node, Line 175  file_pager_read_page (struct node *node,
175      {      {
176        if (num_pending_blocks > 0)        if (num_pending_blocks > 0)
177          {          {
178            block_t dev_block = pending_blocks << log2_dev_blocks_per_fs_block;            store_offset_t dev_block = (store_offset_t) pending_blocks
179                << log2_dev_blocks_per_fs_block;
180            size_t amount = num_pending_blocks << log2_block_size;            size_t amount = num_pending_blocks << log2_block_size;
181            /* The buffer we try to read into; on the first read, we pass in a            /* The buffer we try to read into; on the first read, we pass in a
182               size of zero, so that the read is guaranteed to allocate a new               size of zero, so that the read is guaranteed to allocate a new
# Line 198  file_pager_read_page (struct node *node, Line 203  file_pager_read_page (struct node *node,
203                else                else
204                  /* We've already got some buffer, so copy into it.  */                  /* We've already got some buffer, so copy into it.  */
205                  {                  {
206                    bcopy (new_buf, *buf + offs, new_len);                    memcpy (*buf + offs, new_buf, new_len);
207                    free_page_buf (new_buf); /* Return NEW_BUF to our pool.  */                    free_page_buf (new_buf); /* Return NEW_BUF to our pool.  */
208                    STAT_INC (file_pagein_freed_bufs);                    STAT_INC (file_pagein_freed_bufs);
209                  }                  }
# Line 254  file_pager_read_page (struct node *node, Line 259  file_pager_read_page (struct node *node,
259                  break;                  break;
260                STAT_INC (file_pagein_alloced_bufs);                STAT_INC (file_pagein_alloced_bufs);
261              }              }
262            bzero (*buf + offs, block_size);            memset (*buf + offs, 0, block_size);
263            offs += block_size;            offs += block_size;
264          }          }
265        else        else
# Line 295  pending_blocks_write (struct pending_blo Line 300  pending_blocks_write (struct pending_blo
300    if (pb->num > 0)    if (pb->num > 0)
301      {      {
302        error_t err;        error_t err;
303        block_t dev_block = pb->block << log2_dev_blocks_per_fs_block;        store_offset_t dev_block = (store_offset_t) pb->block
304            << log2_dev_blocks_per_fs_block;
305        size_t length = pb->num << log2_block_size, amount;        size_t length = pb->num << log2_block_size, amount;
306    
307        ext2_debug ("writing block %u[%ld]", pb->block, pb->num);        ext2_debug ("writing block %u[%Ld]", pb->block, pb->num);
308    
309        if (pb->offs > 0)        if (pb->offs > 0)
310          /* Put what we're going to write into a page-aligned buffer.  */          /* Put what we're going to write into a page-aligned buffer.  */
311          {          {
312            void *page_buf = get_page_buf ();            void *page_buf = get_page_buf ();
313            bcopy (pb->buf + pb->offs, (void *)page_buf, length);            memcpy ((void *)page_buf, pb->buf + pb->offs, length);
314            err = store_write (store, dev_block, page_buf, length, &amount);            err = store_write (store, dev_block, page_buf, length, &amount);
315            free_page_buf (page_buf);            free_page_buf (page_buf);
316          }          }
# Line 357  pending_blocks_add (struct pending_block Line 363  pending_blocks_add (struct pending_block
363    return 0;    return 0;
364  }  }
365    
366  /* Write one page for the pager backing NODE, at offset PAGE, into BUF.  This  /* Write one page for the pager backing NODE, at OFFSET, into BUF.  This
367     may need to write several filesystem blocks to satisfy one page, and tries     may need to write several filesystem blocks to satisfy one page, and tries
368     to consolidate the i/o if possible.  */     to consolidate the i/o if possible.  */
369  static error_t  static error_t
# Line 381  file_pager_write_page (struct node *node Line 387  file_pager_write_page (struct node *node
387    else if (offset + left > node->allocsize)    else if (offset + left > node->allocsize)
388      left = node->allocsize - offset;      left = node->allocsize - offset;
389    
390    ext2_debug ("writing inode %d page %d[%d]", node->cache_id, offset, left);    ext2_debug ("writing inode %Ld page %u[%d]", node->cache_id, offset, left);
391    
392    STAT_INC (file_pageouts);    STAT_INC (file_pageouts);
393    
# Line 409  disk_pager_read_page (vm_offset_t page, Line 415  disk_pager_read_page (vm_offset_t page,
415  {  {
416    error_t err;    error_t err;
417    size_t length = vm_page_size, read = 0;    size_t length = vm_page_size, read = 0;
418    vm_size_t dev_end = store->size;    store_offset_t offset = page, dev_end = store->size;
419    
420    if (page + vm_page_size > dev_end)    mutex_lock (&disk_cache_lock);
421      length = dev_end - page;    int index = offset >> log2_block_size;
422      offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size)
423        + offset % block_size;
424      disk_cache_info[index].flags |= DC_INCORE;
425      disk_cache_info[index].flags &=~ DC_UNTOUCHED;
426    #ifndef NDEBUG
427      disk_cache_info[index].last_read = disk_cache_info[index].block;
428      disk_cache_info[index].last_read_xor
429        = disk_cache_info[index].block ^ DISK_CACHE_LAST_READ_XOR;
430    #endif
431      ext2_debug ("(%Ld)", offset >> log2_block_size);
432      mutex_unlock (&disk_cache_lock);
433    
434      if (offset + vm_page_size > dev_end)
435        length = dev_end - offset;
436    
437    err = store_read (store, page >> store->log2_block_size, length, buf, &read);    err = store_read (store, offset >> store->log2_block_size, length,
438                        buf, &read);
439    if (read != length)    if (read != length)
440      return EIO;      return EIO;
441    if (!err && length != vm_page_size)    if (!err && length != vm_page_size)
442      bzero ((void *)(*buf + length), vm_page_size - length);      memset ((void *)(*buf + length), 0, vm_page_size - length);
443    
444    *writelock = 0;    *writelock = 0;
445    
# Line 430  disk_pager_write_page (vm_offset_t page, Line 451  disk_pager_write_page (vm_offset_t page,
451  {  {
452    error_t err = 0;    error_t err = 0;
453    size_t length = vm_page_size, amount;    size_t length = vm_page_size, amount;
454    vm_size_t dev_end = store->size;    store_offset_t offset = page, dev_end = store->size;
455    
456      mutex_lock (&disk_cache_lock);
457      int index = offset >> log2_block_size;
458      assert (disk_cache_info[index].block != DC_NO_BLOCK);
459      offset = ((store_offset_t) disk_cache_info[index].block << log2_block_size)
460        + offset % block_size;
461    #ifndef NDEBUG                  /* Not strictly needed.  */
462      assert ((disk_cache_info[index].last_read ^ DISK_CACHE_LAST_READ_XOR)
463              == disk_cache_info[index].last_read_xor);
464      assert (disk_cache_info[index].last_read
465              == disk_cache_info[index].block);
466    #endif
467      mutex_unlock (&disk_cache_lock);
468    
469    if (page + vm_page_size > dev_end)    if (offset + vm_page_size > dev_end)
470      length = dev_end - page;      length = dev_end - offset;
471    
472    ext2_debug ("writing disk page %d[%d]", page, length);    ext2_debug ("writing disk page %Ld[%d]", offset, length);
473    
474    STAT_INC (disk_pageouts);    STAT_INC (disk_pageouts);
475    
476    if (modified_global_blocks)    if (modified_global_blocks)
477      /* Be picky about which blocks in a page that we write.  */      /* Be picky about which blocks in a page that we write.  */
478      {      {
       vm_offset_t offs = page;  
479        struct pending_blocks pb;        struct pending_blocks pb;
480    
481        pending_blocks_init (&pb, buf);        pending_blocks_init (&pb, buf);
482    
483        while (length > 0 && !err)        while (length > 0 && !err)
484          {          {
485            block_t block = boffs_block (offs);            block_t block = boffs_block (offset);
486    
487            /* We don't clear the block modified bit here because this paging            /* We don't clear the block modified bit here because this paging
488               write request may not be the same one that actually set the bit,               write request may not be the same one that actually set the bit,
# Line 467  disk_pager_write_page (vm_offset_t page, Line 500  disk_pager_write_page (vm_offset_t page,
500              /* Otherwise just skip it.  */              /* Otherwise just skip it.  */
501              err = pending_blocks_skip (&pb);              err = pending_blocks_skip (&pb);
502    
503            offs += block_size;            offset += block_size;
504            length -= block_size;            length -= block_size;
505          }          }
506    
# Line 476  disk_pager_write_page (vm_offset_t page, Line 509  disk_pager_write_page (vm_offset_t page,
509      }      }
510    else    else
511      {      {
512        err = store_write (store, page >> store->log2_block_size,        err = store_write (store, offset >> store->log2_block_size,
513                           buf, length, &amount);                           buf, length, &amount);
514        if (!err && length != amount)        if (!err && length != amount)
515          err = EIO;          err = EIO;
# Line 484  disk_pager_write_page (vm_offset_t page, Line 517  disk_pager_write_page (vm_offset_t page,
517    
518    return err;    return err;
519  }  }
520    
521    static void
522    disk_pager_notify_evict (vm_offset_t page)
523    {
524      int index = page >> log2_block_size;
525    
526      ext2_debug ("(block %u)", index);
527    
528      mutex_lock (&disk_cache_lock);
529      disk_cache_info[index].flags &= ~DC_INCORE;
530      mutex_unlock (&disk_cache_lock);
531    }
532    
533  /* Satisfy a pager read request for either the disk pager or file pager  /* Satisfy a pager read request for either the disk pager or file pager
534     PAGER, to the page at offset PAGE into BUF.  WRITELOCK should be set if     PAGER, to the page at offset PAGE into BUF.  WRITELOCK should be set if
# Line 509  pager_write_page (struct user_pager_info Line 554  pager_write_page (struct user_pager_info
554    else    else
555      return file_pager_write_page (pager->node, page, (void *)buf);      return file_pager_write_page (pager->node, page, (void *)buf);
556  }  }
557    
558    void
559    pager_notify_evict (struct user_pager_info *pager, vm_offset_t page)
560    {
561      if (pager->type == DISK)
562        disk_pager_notify_evict (page);
563    }
564    
565    
566  /* Make page PAGE writable, at least up to ALLOCSIZE.  This function and  /* Make page PAGE writable, at least up to ALLOCSIZE.  This function and
567     diskfs_grow are the only places that blocks are actually added to the     diskfs_grow are the only places that blocks are actually added to the
# Line 558  pager_unlock_page (struct user_pager_inf Line 611  pager_unlock_page (struct user_pager_inf
611    
612  #ifdef EXT2FS_DEBUG  #ifdef EXT2FS_DEBUG
613        if (dn->last_page_partially_writable)        if (dn->last_page_partially_writable)
614          ext2_debug ("made page %u[%lu] in inode %d partially writable",          ext2_debug ("made page %u[%Lu] in inode %Ld partially writable",
615                      page, node->allocsize - page, node->cache_id);                      page, node->allocsize - page, node->cache_id);
616        else        else
617          ext2_debug ("made page %u[%u] in inode %d writable",          ext2_debug ("made page %u[%u] in inode %Ld writable",
618                      page, vm_page_size, node->cache_id);                      page, vm_page_size, node->cache_id);
619  #endif  #endif
620    
# Line 619  diskfs_grow (struct node *node, off_t si Line 672  diskfs_grow (struct node *node, off_t si
672            block_t old_page_end_block =            block_t old_page_end_block =
673              round_page (old_size) >> log2_block_size;              round_page (old_size) >> log2_block_size;
674    
675            ext2_debug ("growing inode %d to %lu bytes (from %lu)", node->cache_id,            ext2_debug ("growing inode %Ld to %Lu bytes (from %Lu)",
676                        new_size, old_size);                        node->cache_id, new_size, old_size);
677    
678            if (dn->last_page_partially_writable            if (dn->last_page_partially_writable
679                && old_page_end_block > end_block)                && old_page_end_block > end_block)
# Line 656  diskfs_grow (struct node *node, off_t si Line 709  diskfs_grow (struct node *node, off_t si
709    
710        STAT_INC (file_grows);        STAT_INC (file_grows);
711    
712        ext2_debug ("new size: %ld%s.", new_size,        ext2_debug ("new size: %Lu%s.", new_size,
713                    dn->last_page_partially_writable                    dn->last_page_partially_writable
714                    ? " (last page writable)": "");                    ? " (last page writable)": "");
715        if (err)        if (err)
716          ext2_warning ("inode=%Ld, target=%Ld: %s",          ext2_warning ("inode=%Ld, target=%Lu: %s",
717                        node->cache_id, new_size, strerror (err));                        node->cache_id, new_size, strerror (err));
718    
719        node->allocsize = new_size;        node->allocsize = new_size;
# Line 765  pager_dropweak (struct user_pager_info * Line 818  pager_dropweak (struct user_pager_info *
818  {  {
819  }  }
820    
821    /* Cached blocks from disk.  */
822    void *disk_cache;
823    
824    /* DISK_CACHE size in bytes and blocks.  */
825    store_offset_t disk_cache_size;
826    int disk_cache_blocks;
827    
828    /* block num --> pointer to in-memory block */
829    hurd_ihash_t disk_cache_bptr;
830    /* Cached blocks' info.  */
831    struct disk_cache_info *disk_cache_info;
832    /* Hint index for which cache block to reuse next.  */
833    int disk_cache_hint;
834    /* Lock for these structures.  */
835    struct mutex disk_cache_lock;
836    /* Fired when a re-association is done.  */
837    struct condition disk_cache_reassociation;
838    
839    /* Finish mapping initialization. */
840    static void
841    disk_cache_init (void)
842    {
843      if (block_size != vm_page_size)
844        ext2_panic ("Block size %d != vm_page_size %d",
845                    block_size, vm_page_size);
846    
847      mutex_init (&disk_cache_lock);
848      condition_init (&disk_cache_reassociation);
849    
850      /* Allocate space for block num -> in-memory pointer mapping.  */
851      if (hurd_ihash_create (&disk_cache_bptr, HURD_IHASH_NO_LOCP))
852        ext2_panic ("Can't allocate memory for disk_pager_bptr");
853    
854      /* Allocate space for disk cache blocks' info.  */
855      disk_cache_info = malloc ((sizeof *disk_cache_info) * disk_cache_blocks);
856      if (!disk_cache_info)
857        ext2_panic ("Cannot allocate space for disk cache info");
858    
859      /* Initialize disk_cache_info.  */
860      for (int i = 0; i < disk_cache_blocks; i++)
861        {
862          disk_cache_info[i].block = DC_NO_BLOCK;
863          disk_cache_info[i].flags = 0;
864          disk_cache_info[i].ref_count = 0;
865    #ifndef NDEBUG
866          disk_cache_info[i].last_read = DC_NO_BLOCK;
867          disk_cache_info[i].last_read_xor
868            = DC_NO_BLOCK ^ DISK_CACHE_LAST_READ_XOR;
869    #endif
870        }
871      disk_cache_hint = 0;
872    
873      /* Map the superblock and the block group descriptors.  */
874      block_t fixed_first = boffs_block (SBLOCK_OFFS);
875      block_t fixed_last = fixed_first
876        + (round_block ((sizeof *group_desc_image) * groups_count)
877           >> log2_block_size);
878      ext2_debug ("%d-%d\n", fixed_first, fixed_last);
879      assert (fixed_last - fixed_first + 1 <= (block_t)disk_cache_blocks + 3);
880      for (block_t i = fixed_first; i <= fixed_last; i++)
881        {
882          buffer_lookup (i);
883          assert (disk_cache_info[i-fixed_first].block == i);
884          disk_cache_info[i-fixed_first].flags |= DC_FIXED;
885        }
886    }
887    
888    static void
889    disk_cache_return_unused (void)
890    {
891      int index;
892    
893      /* XXX: Touch all pages.  It seems that sometimes GNU Mach "forgets"
894         to notify us about evicted pages.  Disk cache must be
895         unlocked.  */
896      for (vm_offset_t i = 0; i < disk_cache_size; i += vm_page_size)
897        *(volatile char *)(disk_cache + i);
898    
899      /* Release some references to cached blocks.  */
900      pokel_sync (&global_pokel, 1);
901    
902      /* Return unused pages that are in core.  */
903      int pending_begin = -1, pending_end = -1;
904      mutex_lock (&disk_cache_lock);
905      for (index = 0; index < disk_cache_blocks; index++)
906        if (! (disk_cache_info[index].flags & (DC_DONT_REUSE & ~DC_INCORE))
907            && ! disk_cache_info[index].ref_count)
908          {
909            ext2_debug ("return %u -> %d",
910                        disk_cache_info[index].block, index);
911            if (index != pending_end)
912              {
913                /* Return previous region, if there is such, ... */
914                if (pending_end >= 0)
915                  {
916                    mutex_unlock (&disk_cache_lock);
917                    pager_return_some (diskfs_disk_pager,
918                                       pending_begin * vm_page_size,
919                                       (pending_end - pending_begin)
920                                       * vm_page_size,
921                                       1);
922                    mutex_lock (&disk_cache_lock);
923                  }
924                /* ... and start new region.  */
925                pending_begin = index;
926              }
927            pending_end = index + 1;
928          }
929    
930      mutex_unlock (&disk_cache_lock);
931    
932      /* Return last region, if there is such.   */
933      if (pending_end >= 0)
934        pager_return_some (diskfs_disk_pager,
935                           pending_begin * vm_page_size,
936                           (pending_end - pending_begin) * vm_page_size,
937                           1);
938      else
939        {
940          printf ("ext2fs: disk cache is starving\n");
941    
942          /* Give it some time.  This should happen rarely.  */
943          sleep (1);
944        }
945    }
946    
947    /* Map block and return pointer to it.  */
948    void *
949    buffer_lookup (block_t block)
950    {
951      int index;
952      void *bptr;
953    
954      assert (0 <= block && block < store->size >> log2_block_size);
955    
956      ext2_debug ("(%u)", block);
957    
958      mutex_lock (&disk_cache_lock);
959    
960      bptr = hurd_ihash_find (disk_cache_bptr, block);
961      if (bptr)
962        /* Already mapped.  */
963        {
964          index = bptr_index (bptr);
965    
966          /* In process of re-associating?  */
967          if (disk_cache_info[index].flags & DC_UNTOUCHED)
968            {
969              /* Wait re-association to finish.  */
970              condition_wait (&disk_cache_reassociation, &disk_cache_lock);
971              mutex_unlock (&disk_cache_lock);
972    
973              /* Try again.  */
974              return buffer_lookup (block); /* tail recursion */
975            }
976    
977          /* Just increment reference and return.  */
978          assert (disk_cache_info[index].ref_count + 1
979                  > disk_cache_info[index].ref_count);
980          disk_cache_info[index].ref_count++;
981    
982          ext2_debug ("cached %u -> %d (ref_count = %d, flags = 0x%x, ptr = %p)",
983                      disk_cache_info[index].block, index,
984                      disk_cache_info[index].ref_count,
985                      disk_cache_info[index].flags, bptr);
986    
987          mutex_unlock (&disk_cache_lock);
988    
989          return bptr;
990        }
991    
992      /* Search for a block that is not in core and is not referenced.  */
993      index = disk_cache_hint;
994      while ((disk_cache_info[index].flags & DC_DONT_REUSE)
995             || (disk_cache_info[index].ref_count))
996        {
997          ext2_debug ("reject %u -> %d (ref_count = %d, flags = 0x%x)",
998                      disk_cache_info[index].block, index,
999                      disk_cache_info[index].ref_count,
1000                      disk_cache_info[index].flags);
1001    
1002          /* Just move to next block.  */
1003          index++;
1004          if (index >= disk_cache_blocks)
1005            index -= disk_cache_blocks;
1006    
1007          /* If we return to where we started, than there is no suitable
1008             block. */
1009          if (index == disk_cache_hint)
1010            break;
1011        }
1012    
1013      /* The next place in the disk cache becomes the current hint.  */
1014      disk_cache_hint = index + 1;
1015      if (disk_cache_hint >= disk_cache_blocks)
1016        disk_cache_hint -= disk_cache_blocks;
1017    
1018      /* Is suitable place found?  */
1019      if ((disk_cache_info[index].flags & DC_DONT_REUSE)
1020          || disk_cache_info[index].ref_count)
1021        /* No place is found.  Try to release some blocks and try
1022           again.  */
1023        {
1024          ext2_debug ("flush %u -> %d", disk_cache_info[index].block, index);
1025    
1026          mutex_unlock (&disk_cache_lock);
1027    
1028          disk_cache_return_unused ();
1029    
1030          return buffer_lookup (block); /* tail recursion */
1031        }
1032    
1033      /* Suitable place is found.  */
1034    
1035      /* Calculate pointer to data.  */
1036      bptr = (char *)disk_cache + (index << log2_block_size);
1037      ext2_debug ("map %u -> %d (%p)", block, index, bptr);
1038    
1039      /* This pager_return_some is used only to set PM_FORCEREAD for the
1040         page.  DC_UNTOUCHED is set so that we catch if someone has
1041         referenced the block while we didn't hold disk_cache_lock.  */
1042      disk_cache_info[index].flags |= DC_UNTOUCHED;
1043    
1044    #if 0 /* XXX: Let's see if this is needed at all.  */
1045    
1046      mutex_unlock (&disk_cache_lock);
1047      pager_return_some (diskfs_disk_pager, bptr - disk_cache, vm_page_size, 1);
1048      mutex_lock (&disk_cache_lock);
1049    
1050      /* Has someone used our bptr?  Has someone mapped requested block
1051         while we have unlocked disk_cache_lock?  If so, environment has
1052         changed and we have to restart operation.  */
1053      if ((! (disk_cache_info[index].flags & DC_UNTOUCHED))
1054          || hurd_ihash_find (disk_cache_bptr, block))
1055        {
1056          mutex_unlock (&disk_cache_lock);
1057          return buffer_lookup (block); /* tail recursion */
1058        }
1059    
1060    #elif 0
1061    
1062      /* XXX: Use libpager internals.  */
1063      
1064      mutex_lock (&diskfs_disk_pager->interlock);
1065      int page = (bptr - disk_cache) / vm_page_size;
1066      assert (page >= 0);
1067      int is_incore = (page < diskfs_disk_pager->pagemapsize
1068                       && (diskfs_disk_pager->pagemap[page] & PM_INCORE));
1069      mutex_unlock (&diskfs_disk_pager->interlock);
1070      if (is_incore)
1071        {
1072          mutex_unlock (&disk_cache_lock);
1073          return buffer_lookup (block); /* tail recursion */
1074        }
1075    
1076    #endif
1077    
1078      /* Re-associate.  */
1079      if (disk_cache_info[index].block != DC_NO_BLOCK)
1080        /* Remove old association.  */
1081        hurd_ihash_remove (disk_cache_bptr, disk_cache_info[index].block);
1082      /* New association.  */
1083      if (hurd_ihash_add (disk_cache_bptr, block, bptr))
1084        ext2_panic ("Couldn't hurd_ihash_add new disk block");
1085      assert (! (disk_cache_info[index].flags & DC_DONT_REUSE & ~DC_UNTOUCHED));
1086      disk_cache_info[index].block = block;
1087      assert (! disk_cache_info[index].ref_count);
1088      disk_cache_info[index].ref_count = 1;
1089    
1090      /* All data structures are set up.  */
1091      mutex_unlock (&disk_cache_lock);
1092    
1093      /* Try to read page.  */
1094      *(volatile char *) bptr;
1095    
1096      /* Check if it's actually read.  */
1097      mutex_lock (&disk_cache_lock);
1098      if (disk_cache_info[index].flags & DC_UNTOUCHED)
1099        /* It's not read.  */
1100        {
1101          /* Remove newly created association.  */
1102          hurd_ihash_remove (disk_cache_bptr, block);
1103          disk_cache_info[index].block = DC_NO_BLOCK;
1104          disk_cache_info[index].flags &=~ DC_UNTOUCHED;
1105          disk_cache_info[index].ref_count = 0;
1106          mutex_unlock (&disk_cache_lock);
1107    
1108          /* Prepare next time association of this page to succeed.  */
1109          pager_flush_some (diskfs_disk_pager, bptr - disk_cache,
1110                            vm_page_size, 0);
1111    
1112          /* Try again.  */
1113          return buffer_lookup (block); /* tail recursion */
1114        }
1115      mutex_unlock (&disk_cache_lock);
1116    
1117      /* Re-association was successful.  */
1118      condition_broadcast (&disk_cache_reassociation);
1119    
1120      ext2_debug ("(%u) = %p", block, bptr);
1121      return bptr;
1122    }
1123    
1124    void
1125    buffer_ref (void *ptr)
1126    {
1127      int index;
1128    
1129      mutex_lock (&disk_cache_lock);
1130      index = bptr_index (ptr);
1131      assert (disk_cache_info[index].ref_count >= 1);
1132      assert (disk_cache_info[index].ref_count + 1
1133              > disk_cache_info[index].ref_count);
1134      disk_cache_info[index].ref_count++;
1135      assert (! (disk_cache_info[index].flags & DC_UNTOUCHED));
1136      ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)",
1137                  ptr,
1138                  disk_cache_info[index].ref_count,
1139                  disk_cache_info[index].flags);
1140      mutex_unlock (&disk_cache_lock);
1141    }
1142    
1143    void
1144    buffer_put (void *ptr)
1145    {
1146      int index;
1147    
1148      assert (disk_cache <= ptr && ptr <= disk_cache + disk_cache_size);
1149    
1150      mutex_lock (&disk_cache_lock);
1151      index = bptr_index (ptr);
1152      ext2_debug ("(%p) (ref_count = %d, flags = 0x%x)",
1153                  ptr,
1154                  disk_cache_info[index].ref_count - 1,
1155                  disk_cache_info[index].flags);
1156      assert (! (disk_cache_info[index].flags & DC_UNTOUCHED));
1157      assert (disk_cache_info[index].ref_count >= 1);
1158      disk_cache_info[index].ref_count--;
1159      mutex_unlock (&disk_cache_lock);
1160    }
1161    
1162    /* Used only in an assertion.  */
1163    int
1164    buffer_is_ref (block_t block)
1165    {
1166      int ref;
1167      void *ptr;
1168    
1169      mutex_lock (&disk_cache_lock);
1170      ptr = hurd_ihash_find (disk_cache_bptr, block);
1171      if (! ptr)
1172        ref = 0;
1173      else                          /* XXX: Should check for DC_UNTOUCHED too.  */
1174        ref = disk_cache_info[bptr_index (ptr)].ref_count;
1175      mutex_unlock (&disk_cache_lock);
1176    
1177      return ref;
1178    }
1179    
1180  /* Create the DISK pager.  */  /* Create the DISK pager.  */
1181  void  void
1182  create_disk_pager (void)  create_disk_pager (void)
# Line 774  create_disk_pager (void) Line 1186  create_disk_pager (void)
1186      ext2_panic ("can't create disk pager: %s", strerror (errno));      ext2_panic ("can't create disk pager: %s", strerror (errno));
1187    upi->type = DISK;    upi->type = DISK;
1188    pager_bucket = ports_create_bucket ();    pager_bucket = ports_create_bucket ();
1189    diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size,    get_hypermetadata ();
1190                             &disk_image);    disk_cache_blocks = DISK_CACHE_BLOCKS;
1191      disk_cache_size = disk_cache_blocks << log2_block_size;
1192      diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 1,
1193                               disk_cache_size, &disk_cache);
1194      disk_cache_init ();
1195  }  }
1196    
1197  /* Call this to create a FILE_DATA pager and return a send right.  /* Call this to create a FILE_DATA pager and return a send right.
# Line 815  diskfs_get_filemap (struct node *node, v Line 1231  diskfs_get_filemap (struct node *node, v
1231            diskfs_nref_light (node);            diskfs_nref_light (node);
1232            node->dn->pager =            node->dn->pager =
1233              pager_create (upi, pager_bucket, MAY_CACHE,              pager_create (upi, pager_bucket, MAY_CACHE,
1234                            MEMORY_OBJECT_COPY_DELAY);                            MEMORY_OBJECT_COPY_DELAY, 0);
1235            if (node->dn->pager == 0)            if (node->dn->pager == 0)
1236              {              {
1237                diskfs_nrele_light (node);                diskfs_nrele_light (node);

Legend:
Removed from v.1.74  
changed lines
  Added in v.1.74.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26