home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / sysv / ialloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  6.4 KB  |  205 lines

  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)
  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.     sb->sv_bh->b_dirt = 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.     bh->b_dirt = 1;
  81.     unlock_super(sb);
  82.     brelse(bh);
  83.     clear_inode(inode);
  84. }
  85.  
  86. struct inode * sysv_new_inode(const struct inode * dir)
  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.     sb->sv_bh->b_dirt = 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.     sb->sv_bh->b_dirt = 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)
  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.             sb->sv_bh->b_dirt = 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.  
  205.