diff options
author | Miles Bader <miles@gnu.org> | 1995-04-12 23:04:26 +0000 |
---|---|---|
committer | Miles Bader <miles@gnu.org> | 1995-04-12 23:04:26 +0000 |
commit | b0ff48880bb401a511e875b5b5c172ca37f7f890 (patch) | |
tree | 887673ff5c1e3ed81cb088882d82133789ea48f8 | |
parent | bd037efbc1e6dbcda1ec0f4353d3c4462b75806b (diff) |
Formerly ialloc.c.~6~
-rw-r--r-- | ext2fs/ialloc.c | 354 |
1 files changed, 168 insertions, 186 deletions
diff --git a/ext2fs/ialloc.c b/ext2fs/ialloc.c index 686c6662..dcc73c8c 100644 --- a/ext2fs/ialloc.c +++ b/ext2fs/ialloc.c @@ -1,5 +1,8 @@ -/* - * Largely stolen from: linux/fs/ext2/ialloc.c +/* Inode allocation routines. + * + * Converted to work under the hurd by Miles Bader <miles@gnu.ai.mit.edu> + * + * Largely stolen from linux/fs/ext2/ialloc.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) @@ -11,10 +14,6 @@ */ /* - * ialloc.c contains the inodes allocation and deallocation routines - */ - -/* * The free inodes are managed by bitmaps. A file system contains several * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap * block for inodes, N blocks for the inode table and data blocks. @@ -26,63 +25,55 @@ */ #include "ext2fs.h" + +/* ---------------------------------------------------------------- */ void -ext2_free_inode (struct inode *inode) +ext2_free_inode (struct node *node, mode_t old_mode) { char *bh; - char *bh2; unsigned long block_group; unsigned long bit; struct ext2_group_desc *gdp; ino_t inum = node->dn->number; - if (!inode) - return; + ext2_debug ("freeing inode %lu\n", inum); - ext2_debug ("freeing inode %lu\n", inode->i_ino); + spin_lock (&sblock_lock); - lock_super (sb); - if (inum < EXT2_FIRST_INO || - inum > sb->u.ext2_sb.s_es->s_inodes_count) + if (inum < EXT2_FIRST_INO || inum > sblock->s_inodes_count) { - ext2_error (sb, "free_inode", - "reserved inode or nonexistent inode"); - unlock_super (sb); + ext2_error ("free_inode", "reserved inode or nonexistent inode"); + spin_unlock (&sblock_lock); return; } - es = sb->u.ext2_sb.s_es; - block_group = (inum - 1) / EXT2_INODES_PER_GROUP (sb); - bit = (inum - 1) % EXT2_INODES_PER_GROUP (sb); - bitmap_nr = load_inode_bitmap (sb, block_group); - bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; + + block_group = (inum - 1) / sblock->s_inodes_per_group; + bit = (inum - 1) % sblock->s_inodes_per_group; + + gdp = group_desc (glock_group); + bh = baddr (gdb->bg_inode_bitmap); + if (!clear_bit (bit, bh)) - ext2_warning (sb, "ext2_free_inode", - "bit already cleared for inode %lu", inum); + ext2_warning ("ext2_free_inode", "bit already cleared for inode %u", inum); else { - gdp = get_group_desc (sb, block_group, &bh2); + record_poke (bh, block_size); + gdp->bg_free_inodes_count++; - if (S_ISDIR (inode->i_mode)) + if (S_ISDIR (old_mode)) gdp->bg_used_dirs_count--; - mark_buffer_dirty (bh2, 1); - es->s_free_inodes_count++; - mark_buffer_dirty (sb->u.ext2_sb.s_sbh, 1); -#if 0 - set_inode_dtime (inode, gdp); -#endif - } - mark_buffer_dirty (bh, 1); - if (sb->s_flags & MS_SYNCHRONOUS) - { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); + record_poke (gdp, sizeof *gdp); + + sblock->s_free_inodes_count++; } - sb->s_dirt = 1; - clear_inode (inode); - unlock_super (sb); + sblock_dirty = 1; + spin_unlock (&sblock_lock); + alloc_sync(0); } + +/* ---------------------------------------------------------------- */ /* * There are two policies for allocating an inode. If the new inode is @@ -94,58 +85,49 @@ ext2_free_inode (struct inode *inode) * For other inodes, search forward from the parent directory\'s block * group to find a free inode. */ -struct inode * -ext2_new_inode (const struct inode *dir, int mode) +ino_t +ext2_alloc_inode (ino_t dir_inum, mode_t mode) { - struct super_block *sb; char *bh; - char *bh2; - int i, j, avefreei; - struct inode *inode; - int bitmap_nr; + int i, j, inum, avefreei; struct ext2_group_desc *gdp; struct ext2_group_desc *tmp; - struct ext2_super_block *es; - if (!dir || !(inode = get_empty_inode ())) - return NULL; - sb = dir->i_sb; - inode->i_sb = sb; - inode->i_flags = sb->s_flags; - lock_super (sb); - es = sb->u.ext2_sb.s_es; + spin_lock (&sblock_lock); + repeat: gdp = NULL; i = 0; if (S_ISDIR (mode)) { - avefreei = es->s_free_inodes_count / - sb->u.ext2_sb.s_groups_count; + avefreei = sblock->s_free_inodes_count / groups_count; + /* I am not yet convinced that this next bit is necessary. - i = dir->u.ext2_i.i_block_group; - for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { - tmp = get_group_desc (sb, i, &bh2); - if ((tmp->bg_used_dirs_count << 8) < - tmp->bg_free_inodes_count) { - gdp = tmp; - break; - } - else - i = ++i % sb->u.ext2_sb.s_groups_count; - } + i = inode_group_num(dir_inum); + for (j = 0; j < groups_count; j++) + { + tmp = group_desc (i); + if ((tmp->bg_used_dirs_count << 8) < tmp->bg_free_inodes_count) + { + gdp = tmp; + break; + } + else + i = ++i % groups_count; + } */ + if (!gdp) { - for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) + for (j = 0; j < groups_count; j++) { - tmp = get_group_desc (sb, j, &bh2); - if (tmp->bg_free_inodes_count && - tmp->bg_free_inodes_count >= avefreei) + tmp = group_desc (j); + if (tmp->bg_free_inodes_count + && tmp->bg_free_inodes_count >= avefreei) { if (!gdp || - (tmp->bg_free_blocks_count > - gdp->bg_free_blocks_count)) + (tmp->bg_free_blocks_count > gdp->bg_free_blocks_count)) { i = j; gdp = tmp; @@ -159,8 +141,8 @@ repeat: /* * Try to place the inode in its parent directory */ - i = dir->u.ext2_i.i_block_group; - tmp = get_group_desc (sb, i, &bh2); + i = inode_group_num(dir_inum); + tmp = group_desc (i); if (tmp->bg_free_inodes_count) gdp = tmp; else @@ -169,12 +151,12 @@ repeat: * Use a quadratic hash to find a group with a * free inode */ - for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) + for (j = 1; j < groups_count; j <<= 1) { i += j; - if (i >= sb->u.ext2_sb.s_groups_count) - i -= sb->u.ext2_sb.s_groups_count; - tmp = get_group_desc (sb, i, &bh2); + if (i >= groups_count) + i -= groups_count; + tmp = group_desc (i); if (tmp->bg_free_inodes_count) { gdp = tmp; @@ -187,12 +169,12 @@ repeat: /* * That failed: try linear search for a free inode */ - i = dir->u.ext2_i.i_block_group + 1; - for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) + i = inode_group_num(dir_inum) + 1; + for (j = 2; j < groups_count; j++) { - if (++i >= sb->u.ext2_sb.s_groups_count) + if (++i >= groups_count) i = 0; - tmp = get_group_desc (sb, i, &bh2); + tmp = group_desc (i); if (tmp->bg_free_inodes_count) { gdp = tmp; @@ -204,101 +186,105 @@ repeat: if (!gdp) { - unlock_super (sb); - iput (inode); - return NULL; + spin_unlock (&sblock_lock); + return 0; } - bitmap_nr = load_inode_bitmap (sb, i); - bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr]; - if ((j = find_first_zero_bit ((unsigned long *) bh, - EXT2_INODES_PER_GROUP (sb))) < - EXT2_INODES_PER_GROUP (sb)) + + bh = gdp->bg_inode_bitmap; + if ((inum = + find_first_zero_bit ((unsigned long *) bh, sblock->s_inodes_per_group)) + < sblock->s_inodes_per_group) { - if (set_bit (j, bh)) + if (set_bit (inum, bh)) { - ext2_warning (sb, "ext2_new_inode", - "bit already set for inode %d", j); + ext2_warning ("ext2_new_inode", + "bit already set for inode %d", inum); goto repeat; } - mark_buffer_dirty (bh, 1); - if (sb->s_flags & MS_SYNCHRONOUS) - { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + record_poke (bh, block_size); } else { if (gdp->bg_free_inodes_count != 0) { - ext2_error (sb, "ext2_new_inode", - "Free inodes count corrupted in group %d", - i); - unlock_super (sb); - iput (inode); - return NULL; + ext2_error ("ext2_new_inode", + "Free inodes count corrupted in group %d", i); + inum = 0; + goto sync_out; } goto repeat; } - j += i * EXT2_INODES_PER_GROUP (sb) + 1; - if (j < EXT2_FIRST_INO || j > es->s_inodes_count) + + inum += i * sblock->s_inodes_per_group + 1; + if (inum < EXT2_FIRST_INO || inum > sblock->s_inodes_count) { - ext2_error (sb, "ext2_new_inode", + ext2_error ("ext2_new_inode", "reserved inode or inode > inodes count - " - "block_group = %d,inode=%d", i, j); - unlock_super (sb); - iput (inode); - return NULL; + "block_group = %d,inode=%d", i, inum); + inum = 0; + goto sync_out; } + gdp->bg_free_inodes_count--; if (S_ISDIR (mode)) gdp->bg_used_dirs_count++; - mark_buffer_dirty (bh2, 1); - es->s_free_inodes_count--; - mark_buffer_dirty (sb->u.ext2_sb.s_sbh, 1); - sb->s_dirt = 1; - inode->i_mode = mode; - inode->i_sb = sb; - inode->i_count = 1; - inode->i_nlink = 1; - inode->i_dev = sb->s_dev; - inode->i_uid = current->fsuid; - if (test_opt (sb, GRPID)) - inode->i_gid = dir->i_gid; - else if (dir->i_mode & S_ISGID) + record_poke (gdp, sizeof *gdp); + + sblock->s_free_inodes_count--; + sblock_dirty = 1; + + sync_out: + spin_unlock (&sblock_lock); + alloc_sync (0); + + return inum; +} + +/* ---------------------------------------------------------------- */ + +error_t +diskfs_alloc_node (const struct node *dir, int mode, struct node **node) +{ + int sex; + struct node *np; + ino_t inum = ext2_alloc_inode (dir->dn->number, mode); + + if (inum == 0) + return ENOSPC; + + err = iget (inum, &np); + if (err) + return err; + + if (np->dn_stat.st_mode) + ext2_panic("Duplicate inode: %d", inum); + + if (np->dn_stat.st_blocks) { - inode->i_gid = dir->i_gid; - if (S_ISDIR (mode)) - mode |= S_ISGID; + ext2_warning("Free inode %d had %d blocks", inum, np->dn_stat.st_blocks); + np->dn_stat.st_blocks = 0; + np->dn_set_ctime = 1; } - else - inode->i_gid = current->fsgid; - inode->i_dirt = 1; - node->dn->number = j; - inode->i_blksize = sb->s_blocksize; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags; - if (S_ISLNK (mode)) - inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL); - inode->u.ext2_i.i_faddr = 0; - inode->u.ext2_i.i_frag_no = 0; - inode->u.ext2_i.i_frag_size = 0; - inode->u.ext2_i.i_file_acl = 0; - inode->u.ext2_i.i_dir_acl = 0; - inode->u.ext2_i.i_dtime = 0; - inode->u.ext2_i.i_block_group = i; - inode->i_op = NULL; - if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) - inode->i_flags |= MS_SYNCHRONOUS; - insert_inode_hash (inode); - inc_inode_version (inode, gdp, mode); - - ext2_debug ("allocating inode %lu\n", node->dn->number); - - unlock_super (sb); - return inode; + + np->dn_stat.st_flags = 0; + + /* + * Set up a new generation number for this inode. + */ + spin_lock (&gennumberlock); + sex = diskfs_mtime->seconds; + if (++nextgennumber < (u_long)sex) + nextgennumber = sex; + np->dn_stat.st_gen = nextgennumber; + spin_unlock (&gennumberlock); + + alloc_sync (np); + + *node = np; + return 0; } + +/* ---------------------------------------------------------------- */ unsigned long ext2_count_free_inodes (struct super_block *sb) @@ -310,63 +296,59 @@ ext2_count_free_inodes (struct super_block *sb) struct ext2_group_desc *gdp; int i; - lock_super (sb); - es = sb->u.ext2_sb.s_es; + spin_lock (&sblock_lock); + desc_count = 0; bitmap_count = 0; gdp = NULL; - for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) + for (i = 0; i < groups_count; i++) { - gdp = get_group_desc (sb, i, NULL); + gdp = group_desc (i); desc_count += gdp->bg_free_inodes_count; - bitmap_nr = load_inode_bitmap (sb, i); - x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr], - EXT2_INODES_PER_GROUP (sb) / 8); - printk ("group %d: stored = %d, counted = %lu\n", - i, gdp->bg_free_inodes_count, x); + x = ext2_count_free (gdp->bg_inode_bitmap, sblock->s_inodes_per_group / 8); + printf ("group %d: stored = %d, counted = %lu\n", i, gdp->bg_free_inodes_count, x); bitmap_count += x; } - printk ("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n", - es->s_free_inodes_count, desc_count, bitmap_count); - unlock_super (sb); + printf ("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n", + sblock->s_free_inodes_count, desc_count, bitmap_count); + spin_unlock (&sblock_lock); return desc_count; #else - return sb->u.ext2_sb.s_es->s_free_inodes_count; + return sblock->s_free_inodes_count; #endif } + +/* ---------------------------------------------------------------- */ void ext2_check_inodes_bitmap (struct super_block *sb) { - struct ext2_super_block *es; - unsigned long desc_count, bitmap_count, x; - int bitmap_nr; - struct ext2_group_desc *gdp; int i; + struct ext2_group_desc *gdp; + unsigned long desc_count, bitmap_count, x; + + spin_lock (&sblock_lock); - lock_super (sb); - es = sb->u.ext2_sb.s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; - for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) + for (i = 0; i < groups_count; i++) { gdp = get_group_desc (sb, i, NULL); desc_count += gdp->bg_free_inodes_count; - bitmap_nr = load_inode_bitmap (sb, i); - x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr], - EXT2_INODES_PER_GROUP (sb) / 8); + x = ext2_count_free (gdp->bg_inode_bitmap, sblock->s_inodes_per_group / 8); if (gdp->bg_free_inodes_count != x) - ext2_error (sb, "ext2_check_inodes_bitmap", + ext2_error ("ext2_check_inodes_bitmap", "Wrong free inodes count in group %d, " "stored = %d, counted = %lu", i, gdp->bg_free_inodes_count, x); bitmap_count += x; } - if (es->s_free_inodes_count != bitmap_count) - ext2_error (sb, "ext2_check_inodes_bitmap", + if (sblock->s_free_inodes_count != bitmap_count) + ext2_error ("ext2_check_inodes_bitmap", "Wrong free inodes count in super block, " "stored = %lu, counted = %lu", - (unsigned long) es->s_free_inodes_count, bitmap_count); - unlock_super (sb); + (unsigned long) sblock->s_free_inodes_count, bitmap_count); + + spin_unlock (&sblock_lock); } |