diff options
author | Miles Bader <miles@gnu.org> | 1995-04-12 20:58:30 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1995-04-12 20:58:30 +0000 |
commit | 5557ab8f1a1ce10dc6778f99ee3ddd22b0b8532c (patch) | |
tree | 37a1bb5610cda76de42730e41e841c59bf3e9604 | |
parent | 91db19aa674476f3e896cb1babb56e13a2a2a368 (diff) |
Formerly getblk.c.~3~
-rw-r--r-- | ext2fs/getblk.c | 309 |
1 files changed, 71 insertions, 238 deletions
diff --git a/ext2fs/getblk.c b/ext2fs/getblk.c index e67494d2..1f3ec58b 100644 --- a/ext2fs/getblk.c +++ b/ext2fs/getblk.c @@ -1,5 +1,5 @@ /* - * Mostly taken from: linux/fs/ext2/inode.c + * Largely stolen from: linux/fs/ext2/inode.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) @@ -15,13 +15,6 @@ * Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 */ -#define inode_bmap(node, nr) ((node)->dn.info.i_data[(nr)]) -static inline int -block_bmap (char *bh, int nr) -{ - return bh ? ((u32 *) bh)[nr] : 0; -} - /* * ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the * superblock in the same manner as are ext2_free_blocks and @@ -30,7 +23,7 @@ block_bmap (char *bh, int nr) * can't block until then. */ void -ext2_discard_prealloc (struct inode *inode) +ext2_discard_prealloc (struct node *node) { #ifdef EXT2_PREALLOCATE if (node->dn->info.i_prealloc_count) @@ -43,7 +36,7 @@ ext2_discard_prealloc (struct inode *inode) } static int -ext2_alloc_block (struct inode *inode, unsigned long goal) +ext2_alloc_block (struct node *node, unsigned long goal) { #ifdef EXT2FS_DEBUG static unsigned long alloc_hits = 0, alloc_attempts = 0; @@ -51,8 +44,6 @@ ext2_alloc_block (struct inode *inode, unsigned long goal) unsigned long result; char *bh; - wait_on_super (sblock); - #ifdef EXT2_PREALLOCATE if (node->dn->info.i_prealloc_count && (goal == node->dn->info.i_prealloc_block || @@ -63,19 +54,12 @@ ext2_alloc_block (struct inode *inode, unsigned long goal) ext2_debug ("preallocation hit (%lu/%lu).\n", ++alloc_hits, ++alloc_attempts); - /* It doesn't matter if we block in getblk() since - we have already atomically allocated the block, and - are only clearing it now. */ - if (!(bh = getblk (result, block_size))) - { - ext2_error ("ext2_alloc_block", "cannot get block %lu", result); - return 0; - } + bh = baddr(result); memset (bh, 0, block_size); } else { - ext2_discard_prealloc (inode); + ext2_discard_prealloc (node); ext2_debug ("preallocation miss (%lu/%lu).\n", alloc_hits, ++alloc_attempts); if (S_ISREG (node->dn_stat.mode)) @@ -93,85 +77,31 @@ ext2_alloc_block (struct inode *inode, unsigned long goal) return result; } - -int -ext2_bmap (struct inode *inode, int block) -{ - int i; - int addr_per_block = EXT2_ADDR_PER_BLOCK (sblock); - - if (block < 0) - { - ext2_warning ("ext2_bmap", "block < 0"); - return 0; - } - if (block >= EXT2_NDIR_BLOCKS + addr_per_block + - addr_per_block * addr_per_block + - addr_per_block * addr_per_block * addr_per_block) - { - ext2_warning ("ext2_bmap", "block > big"); - return 0; - } - if (block < EXT2_NDIR_BLOCKS) - return inode_bmap (inode, block); - block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) - { - i = inode_bmap (inode, EXT2_IND_BLOCK); - if (!i) - return 0; - return block_bmap (baddr (i), block); - } - block -= addr_per_block; - if (block < addr_per_block * addr_per_block) - { - i = inode_bmap (inode, EXT2_DIND_BLOCK); - if (!i) - return 0; - i = block_bmap (baddr (i), block / addr_per_block); - if (!i) - return 0; - return block_bmap (baddr (i), block & (addr_per_block - 1)); - } - block -= addr_per_block * addr_per_block; - i = inode_bmap (inode, EXT2_TIND_BLOCK); - if (!i) - return 0; - i = block_bmap (baddr (i), block / (addr_per_block * addr_per_block)); - if (!i) - return 0; - i = block_bmap (baddr (i), (block / addr_per_block) & (addr_per_block - 1)); - if (!i) - return 0; - return block_bmap (baddr (i), block & (addr_per_block - 1)); -} - -static char * -inode_getblk (struct inode *inode, int nr, - int create, int new_block, int *err) +static error_t +inode_getblk (struct node *node, int nr, + int create, int new_block, int *buf) { u32 *p; int tmp, goal = 0; - char *result; int blocks = block_size / 512; p = node->dn->info.i_data + nr; + repeat: tmp = *p; if (tmp) { - result = getblk (tmp, block_size); + *buf = baddr(tmp); if (tmp == *p) - return result; + return 0; goto repeat; } + if (!create || new_block >= (current->rlim[RLIMIT_FSIZE].rlim_cur >> EXT2_BLOCK_SIZE_BITS (sblock))) - { - *err = -EFBIG; - return NULL; - } + return EFBIG; + if (node->dn->info.i_next_alloc_block == new_block) goal = node->dn->info.i_next_alloc_goal; @@ -195,64 +125,56 @@ repeat: ext2_debug ("goal = %d.\n", goal); - tmp = ext2_alloc_block (inode, goal); + tmp = ext2_alloc_block (node, goal); if (!tmp) - return NULL; - result = getblk (tmp, block_size); + return EIO; + + *buf = baddr(tmp); if (*p) { ext2_free_blocks (tmp, 1); goto repeat; } + *p = tmp; node->dn->info.i_next_alloc_block = new_block; node->dn->info.i_next_alloc_goal = tmp; node->dn_set_ctime = 1; node->dn_stat.st_blocks += blocks; - if (IS_SYNC (inode) || node->dn->info.i_osync) - ext2_sync_inode (inode); + + if (diskfs_synchronous || node->dn->info.i_osync) + ext2_sync_node (node); else node->dirty = 1; - return result; + + return 0; } -static char * -block_getblk (struct inode *inode, +error_t +block_getblk (struct node *node, char *bh, int nr, int create, int blocksize, - int new_block, int *err) + int new_block, int **buf) { int tmp, goal = 0; u32 *p; char *result; int blocks = block_size / 512; - if (!bh) - return NULL; - if (!bh->b_uptodate) - { - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (!bh->b_uptodate) - return NULL; - } p = (u32 *) bh + nr; + repeat: tmp = *p; if (tmp) { - result = getblk (bh->b_dev, tmp, blocksize); + *buf = baddr (tmp); if (tmp == *p) - return result; + return 0; goto repeat; } if (!create || new_block >= - (current->rlim[RLIMIT_FSIZE].rlim_cur >> - EXT2_BLOCK_SIZE_BITS (sblock))) - { - *err = -EFBIG; - return NULL; - } + (current->rlim[RLIMIT_FSIZE].rlim_cur >> EXT2_BLOCK_SIZE_BITS (sblock))) + return EFBIG; if (node->dn->info.i_next_alloc_block == new_block) goal = node->dn->info.i_next_alloc_goal; if (!goal) @@ -268,94 +190,48 @@ repeat: if (!goal) goal = bh->b_blocknr; } - tmp = ext2_alloc_block (inode, goal); + tmp = ext2_alloc_block (node, goal); if (!tmp) - return NULL; + return EIO; /* XXX? */ - result = getblk (bh->b_dev, tmp, blocksize); + *buf = baddr (tmp); if (*p) { ext2_free_blocks (tmp, 1); goto repeat; } *p = tmp; - mark_buffer_dirty (bh, 1); - if (IS_SYNC (inode) || node->dn->info.i_osync) - { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + + if (diskfs_synchronous || node->dn->info.i_osync) + sync_disk_image (bh, block_size); + node->dn_set_ctime = 1; node->dn_stat.st_blocks += blocks; node->dirty = 1; node->dn->info.i_next_alloc_block = new_block; node->dn->info.i_next_alloc_goal = tmp; - return result; -} - -static int -block_getcluster (struct inode *inode, char *bh, - int nr, - int blocksize) -{ - u32 *p; - int firstblock = 0; - int result = 0; - int i; - - /* Check to see if clustering possible here. */ - - if (!bh) - return 0; - - if (nr % (PAGE_SIZE / block_size) != 0) - goto out; - if (nr + 3 > EXT2_ADDR_PER_BLOCK (sblock)) - goto out; - - for (i = 0; i < (PAGE_SIZE / block_size); i++) - { - p = (u32 *) bh + nr + i; - - /* All blocks in cluster must already be allocated */ - if (*p == 0) - goto out; - - /* See if aligned correctly */ - if (i == 0) - firstblock = *p; - else if (*p != firstblock + i) - goto out; - } - - p = (u32 *) bh + nr; - result = generate_cluster (bh->b_dev, (int *) p, blocksize); - -out: - return result; + return 0; } -char * -ext2_getblk (struct inode *inode, long block, - int create, int *err) +error_t +ext2_getblk (struct node *node, long block, int create, char **buf) { char *bh; unsigned long b; unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK (sblock); - *err = -EIO; if (block < 0) { ext2_warning ("ext2_getblk", "block < 0"); - return NULL; + return EIO; } if (block > EXT2_NDIR_BLOCKS + addr_per_block + addr_per_block * addr_per_block + addr_per_block * addr_per_block * addr_per_block) { ext2_warning ("ext2_getblk", "block > big"); - return NULL; + return EIO; } /* * If this is a sequential block allocation, set the next_alloc_block @@ -373,87 +249,44 @@ ext2_getblk (struct inode *inode, long block, node->dn->info.i_next_alloc_goal++; } - *err = -ENOSPC; b = block; - if (block < EXT2_NDIR_BLOCKS) - return inode_getblk (inode, block, create, b, err); - block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) - { - bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, err); - return block_getblk (inode, bh, block, create, - block_size, b, err); - } - block -= addr_per_block; - if (block < addr_per_block * addr_per_block) - { - bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, err); - bh = block_getblk (inode, bh, block / addr_per_block, create, - block_size, b, err); - return block_getblk (inode, bh, block & (addr_per_block - 1), - create, block_size, b, err); - } - block -= addr_per_block * addr_per_block; - bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, err); - bh = block_getblk (inode, bh, block / (addr_per_block * addr_per_block), - create, block_size, b, err); - bh = block_getblk (inode, bh, (block / addr_per_block) & (addr_per_block - 1), - create, block_size, b, err); - return block_getblk (inode, bh, block & (addr_per_block - 1), create, - block_size, b, err); -} - -int -ext2_getcluster (struct inode *inode, long block) -{ - char *bh; - int err, create; - unsigned long b; - unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK (sblock); - - create = 0; - err = -EIO; - if (block < 0) - { - ext2_warning ("ext2_getblk", "block < 0"); - return 0; - } - if (block > EXT2_NDIR_BLOCKS + addr_per_block + - addr_per_block * addr_per_block + - addr_per_block * addr_per_block * addr_per_block) - { - ext2_warning ("ext2_getblk", "block > big"); - return 0; - } - err = -ENOSPC; - b = block; if (block < EXT2_NDIR_BLOCKS) - return 0; + return inode_getblk (node, block, create, b, buf); block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) { - bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, &err); - return block_getcluster (inode, bh, block, - block_size); + err = inode_getblk (node, EXT2_IND_BLOCK, create, b, &bh); + if (!err) + err = block_getblk (node, bh, block, create, block_size, b, buf); + return err; } + block -= addr_per_block; if (block < addr_per_block * addr_per_block) { - bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, &err); - bh = block_getblk (inode, bh, block / addr_per_block, create, - block_size, b, &err); - return block_getcluster (inode, bh, block & (addr_per_block - 1), - block_size); + err = inode_getblk (node, EXT2_DIND_BLOCK, create, b, &bh); + if (!err) + err = block_getblk (node, bh, block / addr_per_block, create, + block_size, b, &bh); + if (!err) + err = block_getblk (node, bh, block & (addr_per_block - 1), + create, block_size, b, buf); + return err; } + block -= addr_per_block * addr_per_block; - bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, &err); - bh = block_getblk (inode, bh, block / (addr_per_block * addr_per_block), - create, block_size, b, &err); - bh = block_getblk (inode, bh, (block / addr_per_block) & (addr_per_block - 1), - create, block_size, b, &err); - return block_getcluster (inode, bh, block & (addr_per_block - 1), - block_size); + err = inode_getblk (node, EXT2_TIND_BLOCK, create, b, bh); + if (!err) + err = block_getblk (node, bh, block / (addr_per_block * addr_per_block), + create, block_size, b, &bh); + if (!err) + err = + block_getblk (node, bh, (block / addr_per_block) & (addr_per_block - 1), + create, block_size, b, &bh); + if (!err) + err = block_getblk (node, bh, block & (addr_per_block - 1), create, + block_size, b, buf); + return err; } |