home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / sysv / ialloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  6.9 KB  |  223 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. #ifdef MODULE
  23. #include <linux/module.h>
  24. #endif
  25.  
  26. #include <linux/sched.h>
  27. #include <linux/kernel.h>
  28. #include <linux/fs.h>
  29. #include <linux/sysv_fs.h>
  30. #include <linux/stddef.h>
  31. #include <linux/stat.h>
  32. #include <linux/string.h>
  33. #include <linux/locks.h>
  34.  
  35. /* We don't trust the value of
  36.    sb->sv_sbd2->s_tinode = *sb->sv_sb_total_free_inodes
  37.    but we nevertheless keep it up to date. */
  38.  
  39. /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
  40.  
  41. /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
  42. static inline sysv_ino_t * sv_sb_fic_inode (struct super_block * sb, unsigned int i)
  43. {
  44.     if (sb->sv_bh1 == sb->sv_bh2)
  45.         return &sb->sv_sb_fic_inodes[i];
  46.     else {
  47.         /* 512 byte Xenix FS */
  48.         unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
  49.         if (offset < 512)
  50.             return (sysv_ino_t*)(sb->sv_sbd1 + offset);
  51.         else
  52.             return (sysv_ino_t*)(sb->sv_sbd2 + offset);
  53.     }
  54. }
  55.  
  56. void sysv_free_inode(struct inode * inode)
  57. {
  58.     struct super_block * sb;
  59.     unsigned int ino;
  60.     struct buffer_head * bh;
  61.     struct sysv_inode * raw_inode;
  62.  
  63.     if (!inode)
  64.         return;
  65.     if (!inode->i_dev) {
  66.         printk("sysv_free_inode: inode has no device\n");
  67.         return;
  68.     }
  69.     if (inode->i_count != 1) {
  70.         printk("sysv_free_inode: inode has count=%d\n", inode->i_count);
  71.         return;
  72.     }
  73.     if (inode->i_nlink) {
  74.         printk("sysv_free_inode: inode has nlink=%d\n", inode->i_nlink);
  75.         return;
  76.     }
  77.     if (!(sb = inode->i_sb)) {
  78.         printk("sysv_free_inode: inode on nonexistent device\n");
  79.         return;
  80.     }
  81.     ino = inode->i_ino;
  82.     if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) {
  83.         printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
  84.         return;
  85.     }
  86.     if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) {
  87.         printk("sysv_free_inode: unable to read inode block on device %d/%d\n",MAJOR(inode->i_dev),MINOR(inode->i_dev));
  88.         clear_inode(inode);
  89.         return;
  90.     }
  91.     raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
  92.     lock_super(sb);
  93.     if (*sb->sv_sb_fic_count < sb->sv_fic_size)
  94.         *sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino;
  95.     (*sb->sv_sb_total_free_inodes)++;
  96.     mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
  97.     if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
  98.     sb->s_dirt = 1; /* and needs time stamp */
  99.     memset(raw_inode, 0, sizeof(struct sysv_inode));
  100.     mark_buffer_dirty(bh, 1);
  101.     unlock_super(sb);
  102.     brelse(bh);
  103.     clear_inode(inode);
  104. }
  105.  
  106. struct inode * sysv_new_inode(const struct inode * dir)
  107. {
  108.     struct inode * inode;
  109.     struct super_block * sb;
  110.     struct buffer_head * bh;
  111.     struct sysv_inode * raw_inode;
  112.     int i,j,ino,block;
  113.  
  114.     if (!dir || !(inode = get_empty_inode()))
  115.         return NULL;
  116.     sb = dir->i_sb;
  117.     inode->i_sb = sb;
  118.     inode->i_flags = inode->i_sb->s_flags;
  119.     lock_super(sb);        /* protect against task switches */
  120.     if ((*sb->sv_sb_fic_count == 0)
  121.         || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */
  122.        ) {
  123.         /* Rebuild cache of free inodes: */
  124.         /* i : index into cache slot being filled         */
  125.         /* ino : inode we are trying                 */
  126.         /* block : firstinodezone + (ino-1)/inodes_per_block */
  127.         /* j : (ino-1)%inodes_per_block                 */
  128.         /* bh : buffer for block                 */
  129.         /* raw_inode : pointer to inode ino in the block     */
  130.         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) {
  131.             if (!(bh = sv_bread(sb, sb->s_dev, block))) {
  132.                 printk("sysv_new_inode: unable to read inode table\n");
  133.                 break;    /* go with what we've got */
  134.                 /* FIXME: Perhaps try the next block? */
  135.             }
  136.             raw_inode = (struct sysv_inode *) bh->b_data + j;
  137.             for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
  138.                 if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
  139.                     *sv_sb_fic_inode(sb,i++) = ino;
  140.             }
  141.             brelse(bh);
  142.         }
  143.         if (i == 0) {
  144.             iput(inode);
  145.             unlock_super(sb);
  146.             return NULL;    /* no inodes available */
  147.         }
  148.         *sb->sv_sb_fic_count = i;
  149.     }
  150.     /* Now *sb->sv_sb_fic_count > 0. */
  151.     ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count));
  152.     mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
  153.     if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
  154.     sb->s_dirt = 1; /* and needs time stamp */
  155.     inode->i_count = 1;
  156.     inode->i_nlink = 1;
  157.     inode->i_dev = sb->s_dev;
  158.     inode->i_uid = current->fsuid;
  159.     inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
  160.     inode->i_dirt = 1;
  161.     inode->i_ino = ino;
  162.     inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  163.     inode->i_op = NULL;
  164.     inode->i_blocks = inode->i_blksize = 0;
  165.     insert_inode_hash(inode);
  166.     /* Change directory entry: */
  167.     inode->i_mode = 0;        /* for sysv_write_inode() */
  168.     inode->i_size = 0;        /* ditto */
  169.     sysv_write_inode(inode);    /* ensure inode not allocated again */
  170.                     /* FIXME: caller may call this too. */
  171.     inode->i_dirt = 1;        /* cleared by sysv_write_inode() */
  172.     /* That's it. */
  173.     (*sb->sv_sb_total_free_inodes)--;
  174.     mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */
  175.     sb->s_dirt = 1; /* and needs time stamp again */
  176.     unlock_super(sb);
  177.     return inode;
  178. }
  179.  
  180. unsigned long sysv_count_free_inodes(struct super_block * sb)
  181. {
  182. #if 1 /* test */
  183.     struct buffer_head * bh;
  184.     struct sysv_inode * raw_inode;
  185.     int j,block,count;
  186.  
  187.     /* this causes a lot of disk traffic ... */
  188.     count = 0;
  189.     lock_super(sb);
  190.     /* i : index into cache slot being filled         */
  191.     /* ino : inode we are trying                 */
  192.     /* block : firstinodezone + (ino-1)/inodes_per_block */
  193.     /* j : (ino-1)%inodes_per_block                 */
  194.     /* bh : buffer for block                 */
  195.     /* raw_inode : pointer to inode ino in the block     */
  196.     for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
  197.         if (!(bh = sv_bread(sb, sb->s_dev, block))) {
  198.             printk("sysv_count_free_inodes: unable to read inode table\n");
  199.             break;    /* go with what we've got */
  200.             /* FIXME: Perhaps try the next block? */
  201.         }
  202.         raw_inode = (struct sysv_inode *) bh->b_data + j;
  203.         for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
  204.             if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
  205.                 count++;
  206.         brelse(bh);
  207.     }
  208.     if (count != *sb->sv_sb_total_free_inodes) {
  209.         printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
  210.         if (!(sb->s_flags & MS_RDONLY)) {
  211.             *sb->sv_sb_total_free_inodes = count;
  212.             mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */
  213.             sb->s_dirt = 1; /* and needs time stamp */
  214.         }
  215.     }
  216.     unlock_super(sb);
  217.     return count;
  218. #else
  219.     return *sb->sv_sb_total_free_inodes;
  220. #endif
  221. }
  222.  
  223.