root/fs/sysv/ialloc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sysv_free_inode
  2. sysv_new_inode
  3. sysv_count_free_inodes

   1 /*
   2  *  linux/fs/sysv/ialloc.c
   3  *
   4  *  minix/bitmap.c
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  *
   7  *  ext/freelists.c
   8  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
   9  *
  10  *  xenix/alloc.c
  11  *  Copyright (C) 1992  Doug Evans
  12  *
  13  *  coh/alloc.c
  14  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  15  *
  16  *  sysv/ialloc.c
  17  *  Copyright (C) 1993  Bruno Haible
  18  *
  19  *  This file contains code for allocating/freeing inodes.
  20  */
  21 
  22 #include <linux/sched.h>
  23 #include <linux/kernel.h>
  24 #include <linux/fs.h>
  25 #include <linux/sysv_fs.h>
  26 #include <linux/stat.h>
  27 #include <linux/string.h>
  28 #include <linux/locks.h>
  29 
  30 /* We don't trust the value of
  31    sb->sv_sbd->s_tinode = *sb->sv_sb_total_free_inodes
  32    but we nevertheless keep it up to date. */
  33 
  34 /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
  35 
  36 void sysv_free_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38         struct super_block * sb;
  39         unsigned int ino;
  40         struct buffer_head * bh;
  41         char * bh_data;
  42         struct sysv_inode * raw_inode;
  43 
  44         if (!inode)
  45                 return;
  46         if (!inode->i_dev) {
  47                 printk("sysv_free_inode: inode has no device\n");
  48                 return;
  49         }
  50         if (inode->i_count != 1) {
  51                 printk("sysv_free_inode: inode has count=%d\n", inode->i_count);
  52                 return;
  53         }
  54         if (inode->i_nlink) {
  55                 printk("sysv_free_inode: inode has nlink=%d\n", inode->i_nlink);
  56                 return;
  57         }
  58         if (!(sb = inode->i_sb)) {
  59                 printk("sysv_free_inode: inode on nonexistent device\n");
  60                 return;
  61         }
  62         ino = inode->i_ino;
  63         if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) {
  64                 printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
  65                 return;
  66         }
  67         if (!(bh = sysv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits), &bh_data))) {
  68                 printk("sysv_free_inode: unable to read inode block on device %d/%d\n",MAJOR(inode->i_dev),MINOR(inode->i_dev));
  69                 clear_inode(inode);
  70                 return;
  71         }
  72         raw_inode = (struct sysv_inode *) bh_data + ((ino-1) & sb->sv_inodes_per_block_1);
  73         lock_super(sb);
  74         if (*sb->sv_sb_fic_count < sb->sv_fic_size)
  75                 sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)++] = ino;
  76         (*sb->sv_sb_total_free_inodes)++;
  77         mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
  78         sb->s_dirt = 1; /* and needs time stamp */
  79         memset(raw_inode, 0, sizeof(struct sysv_inode));
  80         mark_buffer_dirty(bh, 1);
  81         unlock_super(sb);
  82         brelse(bh);
  83         clear_inode(inode);
  84 }
  85 
  86 struct inode * sysv_new_inode(const struct inode * dir)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88         struct inode * inode;
  89         struct super_block * sb;
  90         struct buffer_head * bh;
  91         char * bh_data;
  92         struct sysv_inode * raw_inode;
  93         int i,j,ino,block;
  94 
  95         if (!dir || !(inode = get_empty_inode()))
  96                 return NULL;
  97         sb = dir->i_sb;
  98         inode->i_sb = sb;
  99         inode->i_flags = inode->i_sb->s_flags;
 100         lock_super(sb);         /* protect against task switches */
 101         if ((*sb->sv_sb_fic_count == 0)
 102             || (sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)-1] == 0) /* Applies only to SystemV2 FS */
 103            ) {
 104                 /* Rebuild cache of free inodes: */
 105                 /* i : index into cache slot being filled            */
 106                 /* ino : inode we are trying                         */
 107                 /* block : firstinodezone + (ino-1)/inodes_per_block */
 108                 /* j : (ino-1)%inodes_per_block                      */
 109                 /* bh : buffer for block                             */
 110                 /* raw_inode : pointer to inode ino in the block     */
 111                 for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) {
 112                         if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {
 113                                 printk("sysv_new_inode: unable to read inode table\n");
 114                                 break;  /* go with what we've got */
 115                                 /* FIXME: Perhaps try the next block? */
 116                         }
 117                         raw_inode = (struct sysv_inode *) bh_data + j;
 118                         for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
 119                                 if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
 120                                         sb->sv_sb_fic_inodes[i++] = ino;
 121                         }
 122                         brelse(bh);
 123                 }
 124                 if (i == 0) {
 125                         iput(inode);
 126                         unlock_super(sb);
 127                         return NULL;    /* no inodes available */
 128                 }
 129                 *sb->sv_sb_fic_count = i;
 130         }
 131         /* Now *sb->sv_sb_fic_count > 0. */
 132         ino = sb->sv_sb_fic_inodes[--(*sb->sv_sb_fic_count)];
 133         mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
 134         sb->s_dirt = 1; /* and needs time stamp */
 135         inode->i_count = 1;
 136         inode->i_nlink = 1;
 137         inode->i_dev = sb->s_dev;
 138         inode->i_uid = current->euid;
 139         inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->egid;
 140         inode->i_dirt = 1;
 141         inode->i_ino = ino;
 142         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 143         inode->i_op = NULL;
 144         inode->i_blocks = inode->i_blksize = 0;
 145         inode->u.sysv_i.i_lock = 0; inode->u.sysv_i.i_wait = NULL;
 146         insert_inode_hash(inode);
 147         /* Change directory entry: */
 148         inode->i_mode = 0;              /* for sysv_write_inode() */
 149         inode->i_size = 0;              /* ditto */
 150         sysv_write_inode(inode);        /* ensure inode not allocated again */
 151                                         /* FIXME: caller may call this too. */
 152         inode->i_dirt = 1;              /* cleared by sysv_write_inode() */
 153         /* That's it. */
 154         (*sb->sv_sb_total_free_inodes)--;
 155         mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified again */
 156         sb->s_dirt = 1; /* and needs time stamp again */
 157         unlock_super(sb);
 158         return inode;
 159 }
 160 
 161 unsigned long sysv_count_free_inodes(struct super_block * sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163 #if 1 /* test */
 164         struct buffer_head * bh;
 165         char * bh_data;
 166         struct sysv_inode * raw_inode;
 167         int j,block,count;
 168 
 169         /* this causes a lot of disk traffic ... */
 170         count = 0;
 171         lock_super(sb);
 172         /* i : index into cache slot being filled            */
 173         /* ino : inode we are trying                         */
 174         /* block : firstinodezone + (ino-1)/inodes_per_block */
 175         /* j : (ino-1)%inodes_per_block                      */
 176         /* bh : buffer for block                             */
 177         /* raw_inode : pointer to inode ino in the block     */
 178         for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
 179                 if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {
 180                         printk("sysv_count_free_inodes: unable to read inode table\n");
 181                         break;  /* go with what we've got */
 182                         /* FIXME: Perhaps try the next block? */
 183                 }
 184                 raw_inode = (struct sysv_inode *) bh_data + j;
 185                 for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
 186                         if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
 187                                 count++;
 188                 brelse(bh);
 189         }
 190         if (count != *sb->sv_sb_total_free_inodes) {
 191                 printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
 192                 if (!(sb->s_flags & MS_RDONLY)) {
 193                         *sb->sv_sb_total_free_inodes = count;
 194                         mark_buffer_dirty(sb->sv_bh, 1); /* super-block has been modified */
 195                         sb->s_dirt = 1; /* and needs time stamp */
 196                 }
 197         }
 198         unlock_super(sb);
 199         return count;
 200 #else
 201         return *sb->sv_sb_total_free_inodes;
 202 #endif
 203 }
 204 

/* [previous][next][first][last][top][bottom][index][help] */