From ea4802bc0975218544cb447df37b704f60ef2fde Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Fri, 3 May 2013 19:56:51 +0200 Subject: Large store support for ext2fs This is a revised version of the large store patch for ext2fs, written by Ognyan Kulev. It provides support for stores larger than 2 GiB. * ext2fs/balloc.c: Use the new disk_cache_block_ref and disk_cache_block_deref functions to access blocks from the disk cache. * ext2fs/ext2fs.c (main): Update initialization call to pokel_init, and call map_hypermetadata instead of get_hypermetadata. * ext2fs/ext2fs.h: Include and . (DISK_CACHE_BLOCKS): New macro. (DC_INCORE): Likewise. (DC_UNTOUCHED): Likewise. (DC_FIXED): Likewise. (DC_DONT_REUSE): Likewise. (DC_NO_BLOCK): Likewise. (DISK_CACHE_LAST_READ_XOR) [!NDEBUG]: Likewise. (struct disk_cache_info): New structure. (disk_cache): New external variable. (disk_cache_size): Likewise. (disk_cache_blocks): Likewise. (disk_cache_bptr): Likewise. (disk_cache_info): Likewise. (disk_cache_lock): Likewise. (disk_cache_reassociation): Likewise. (disk_cache_block_ref): New declaration. (disk_cache_block_ref_ptr): Likewise. (disk_cache_block_deref): Likewise. (disk_cache_block_is_ref): Likewise. (map_hypermetadata): Likewise. (trunc_block): Cast to off_t. (round_block): Likewise. (boffs): Likewise. (bptr_index): New macro. (boffs_ptr): Rewrite as an inline function to make it look up a block from the disk cache. (bptr_offs): Likewise. (dino): Remove function, replaced with ... (dino_ref): ... this one, which adds a reference to the inode block. (dino_deref): New inline function. (record_global_poke): Make sure block is referenced. (record_indir_poke): Likewise. (sync_global_ptr): Remove block reference, and adjust call to pager_sync_some. (sync_global): Add debug call to print wait parameter. * ext2fs/getblk.c: Use the new disk_cache_block_ref and disk_cache_block_deref functions to access blocks from the disk cache. * ext2fs/hyper.c (get_hypermetadata): Read the superblock from the store now that it's not directly mapped in memory. Move the initialization of zeroblock here from ... (map_hypermetadata): ... here. Also, set the superblock pointer. (diskfs_set_hypermetadata): Add a reference to the superblock. (diskfs_readonly_changed): Update call to mprotect. * ext2fs/ialloc.c: Use the new disk_cache_block_ref, disk_cache_block_ref_ptr and disk_cache_block_deref functions to access blocks from the disk cache. * ext2fs/inode.c: Update calls that used the disk image to use the disk cache, and use the new reference handling functions where appropriate. * ext2fs/pager.c: Include and "../libpager/priv.h". (disk_image): Remove global variable. (disk_pager_read_page): Update cache information. (disk_pager_write_page): Likewise. (disk_pager_notify_evict): New function. (pager_notify_evict): Call disk_pager_notify_evict appropriately. (disk_cache): New global variable. (disk_cache_size): Likewise. (disk_cache_blocks): Likewise. (disk_cache_bptr): Likewise. (disk_cache_info): Likewise. (disk_cache_hint): Likewise. (disk_cache_lock): Likewise. (disk_cache_reassociation): Likewise. (disk_cache_init): New function. (disk_cache_return_unused): Likewise. (disk_cache_block_ref): Likewise. (disk_cache_block_ref_ptr): Likewise. (disk_cache_block_deref): Likewise. (disk_cache_block_is_ref): Likewise. (create_disk_pager): Update initialization of the disk pager. * ext2fs/pokel.c (pokel_add): Drop block references with disk_cache_block_deref. (_pokel_exec): Likewise. * ext2fs/truncate.c (trunc_indirect): Use the new disk_cache_block_ref and disk_cache_block_deref functions to access blocks from the disk cache. --- ext2fs/inode.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'ext2fs/inode.c') diff --git a/ext2fs/inode.c b/ext2fs/inode.c index 2c442795..e75c63f9 100644 --- a/ext2fs/inode.c +++ b/ext2fs/inode.c @@ -92,7 +92,7 @@ diskfs_cached_lookup (ino_t inum, struct node **npp) dn->dir_idx = 0; dn->pager = 0; pthread_rwlock_init (&dn->alloc_lock, NULL); - pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_image); + pokel_init (&dn->indir_pokel, diskfs_disk_pager, disk_cache); /* Create the new node. */ np = diskfs_make_node (dn); @@ -201,13 +201,17 @@ read_node (struct node *np) error_t err; struct stat *st = &np->dn_stat; struct disknode *dn = np->dn; - struct ext2_inode *di = dino (np->cache_id); + struct ext2_inode *di; struct ext2_inode_info *info = &dn->info; + ext2_debug ("(%llu)", np->cache_id); + err = diskfs_catch_exception (); if (err) return err; + di = dino_ref (np->cache_id); + st->st_fstype = FSTYPE_EXT2FS; st->st_fsid = getpid (); /* This call is very cheap. */ st->st_ino = np->cache_id; @@ -285,7 +289,9 @@ read_node (struct node *np) info->i_high_size = di->i_size_high; if (info->i_high_size) /* XXX */ { + dino_deref (di); ext2_warning ("cannot handle large file inode %Ld", np->cache_id); + diskfs_end_catch_exception (); return EFBIG; } } @@ -307,6 +313,7 @@ read_node (struct node *np) } dn->info_i_translator = di->i_translator; + dino_deref (di); diskfs_end_catch_exception (); if (S_ISREG (st->st_mode) || S_ISDIR (st->st_mode) @@ -408,7 +415,9 @@ write_node (struct node *np) { error_t err; struct stat *st = &np->dn_stat; - struct ext2_inode *di = dino (np->cache_id); + struct ext2_inode *di; + + ext2_debug ("(%llu)", np->cache_id); if (np->dn->info.i_prealloc_count) ext2_discard_prealloc (np); @@ -425,6 +434,8 @@ write_node (struct node *np) if (err) return NULL; + di = dino_ref (np->cache_id); + di->i_generation = st->st_gen; /* We happen to know that the stat mode bits are the same @@ -505,6 +516,7 @@ write_node (struct node *np) diskfs_end_catch_exception (); np->dn_stat_dirty = 0; + /* Leave invoking dino_deref (di) to the caller. */ return di; } else @@ -674,7 +686,7 @@ diskfs_set_translator (struct node *np, const char *name, unsigned namelen, if (err) return err; - di = dino (np->cache_id); + di = dino_ref (np->cache_id); blkno = di->i_translator; if (namelen && !blkno) @@ -687,6 +699,7 @@ diskfs_set_translator (struct node *np, const char *name, unsigned namelen, 0, 0, 0); if (blkno == 0) { + dino_deref (di); diskfs_end_catch_exception (); return ENOSPC; } @@ -710,15 +723,20 @@ diskfs_set_translator (struct node *np, const char *name, unsigned namelen, np->dn_stat.st_mode &= ~S_IPTRANS; np->dn_set_ctime = 1; } + else + dino_deref (di); if (namelen) { + void *blkptr; + buf[0] = namelen & 0xFF; buf[1] = (namelen >> 8) & 0xFF; bcopy (name, buf + 2, namelen); - bcopy (buf, bptr (blkno), block_size); - record_global_poke (bptr (blkno)); + blkptr = disk_cache_block_ref (blkno); + memcpy (blkptr, buf, block_size); + record_global_poke (blkptr); np->dn_stat.st_mode |= S_IPTRANS; np->dn_set_ctime = 1; @@ -736,7 +754,8 @@ diskfs_get_translator (struct node *np, char **namep, unsigned *namelen) error_t err = 0; daddr_t blkno; unsigned datalen; - const void *transloc; + void *transloc; + struct ext2_inode *di; assert (sblock->s_creator_os == EXT2_OS_HURD); @@ -744,9 +763,11 @@ diskfs_get_translator (struct node *np, char **namep, unsigned *namelen) if (err) return err; - blkno = (dino (np->cache_id))->i_translator; + di = dino_ref (np->cache_id); + blkno = di->i_translator; + dino_deref (di); assert (blkno); - transloc = bptr (blkno); + transloc = disk_cache_block_ref (blkno); datalen = ((unsigned char *)transloc)[0] + (((unsigned char *)transloc)[1] << 8); @@ -761,6 +782,7 @@ diskfs_get_translator (struct node *np, char **namep, unsigned *namelen) memcpy (*namep, transloc + 2, datalen); } + disk_cache_block_deref (transloc); diskfs_end_catch_exception (); *namelen = datalen; -- cgit v1.2.3