linux/fs/sysv/ialloc.c
<<
>>
Prefs
   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/kernel.h>
  23#include <linux/stddef.h>
  24#include <linux/sched.h>
  25#include <linux/stat.h>
  26#include <linux/string.h>
  27#include <linux/buffer_head.h>
  28#include "sysv.h"
  29
  30/* We don't trust the value of
  31   sb->sv_sbd2->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/* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
  37static inline sysv_ino_t *
  38sv_sb_fic_inode(struct super_block * sb, unsigned int i)
  39{
  40        struct sysv_sb_info *sbi = SYSV_SB(sb);
  41
  42        if (sbi->s_bh1 == sbi->s_bh2)
  43                return &sbi->s_sb_fic_inodes[i];
  44        else {
  45                /* 512 byte Xenix FS */
  46                unsigned int offset = offsetof(struct xenix_super_block, s_inode[i]);
  47                if (offset < 512)
  48                        return (sysv_ino_t*)(sbi->s_sbd1 + offset);
  49                else
  50                        return (sysv_ino_t*)(sbi->s_sbd2 + offset);
  51        }
  52}
  53
  54struct sysv_inode *
  55sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh)
  56{
  57        struct sysv_sb_info *sbi = SYSV_SB(sb);
  58        struct sysv_inode *res;
  59        int block = sbi->s_firstinodezone + sbi->s_block_base;
  60
  61        block += (ino-1) >> sbi->s_inodes_per_block_bits;
  62        *bh = sb_bread(sb, block);
  63        if (!*bh)
  64                return NULL;
  65        res = (struct sysv_inode *)(*bh)->b_data;
  66        return res + ((ino-1) & sbi->s_inodes_per_block_1);
  67}
  68
  69static int refill_free_cache(struct super_block *sb)
  70{
  71        struct sysv_sb_info *sbi = SYSV_SB(sb);
  72        struct buffer_head * bh;
  73        struct sysv_inode * raw_inode;
  74        int i = 0, ino;
  75
  76        ino = SYSV_ROOT_INO+1;
  77        raw_inode = sysv_raw_inode(sb, ino, &bh);
  78        if (!raw_inode)
  79                goto out;
  80        while (ino <= sbi->s_ninodes) {
  81                if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) {
  82                        *sv_sb_fic_inode(sb,i++) = cpu_to_fs16(SYSV_SB(sb), ino);
  83                        if (i == sbi->s_fic_size)
  84                                break;
  85                }
  86                if ((ino++ & sbi->s_inodes_per_block_1) == 0) {
  87                        brelse(bh);
  88                        raw_inode = sysv_raw_inode(sb, ino, &bh);
  89                        if (!raw_inode)
  90                                goto out;
  91                } else
  92                        raw_inode++;
  93        }
  94        brelse(bh);
  95out:
  96        return i;
  97}
  98
  99void sysv_free_inode(struct inode * inode)
 100{
 101        struct super_block *sb = inode->i_sb;
 102        struct sysv_sb_info *sbi = SYSV_SB(sb);
 103        unsigned int ino;
 104        struct buffer_head * bh;
 105        struct sysv_inode * raw_inode;
 106        unsigned count;
 107
 108        sb = inode->i_sb;
 109        ino = inode->i_ino;
 110        if (ino <= SYSV_ROOT_INO || ino > sbi->s_ninodes) {
 111                printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
 112                return;
 113        }
 114        raw_inode = sysv_raw_inode(sb, ino, &bh);
 115        clear_inode(inode);
 116        if (!raw_inode) {
 117                printk("sysv_free_inode: unable to read inode block on device "
 118                       "%s\n", inode->i_sb->s_id);
 119                return;
 120        }
 121        lock_super(sb);
 122        count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
 123        if (count < sbi->s_fic_size) {
 124                *sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sbi, ino);
 125                *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);
 126        }
 127        fs16_add(sbi, sbi->s_sb_total_free_inodes, 1);
 128        dirty_sb(sb);
 129        memset(raw_inode, 0, sizeof(struct sysv_inode));
 130        mark_buffer_dirty(bh);
 131        unlock_super(sb);
 132        brelse(bh);
 133}
 134
 135struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
 136{
 137        struct super_block *sb = dir->i_sb;
 138        struct sysv_sb_info *sbi = SYSV_SB(sb);
 139        struct inode *inode;
 140        sysv_ino_t ino;
 141        unsigned count;
 142
 143        inode = new_inode(sb);
 144        if (!inode)
 145                return ERR_PTR(-ENOMEM);
 146
 147        lock_super(sb);
 148        count = fs16_to_cpu(sbi, *sbi->s_sb_fic_count);
 149        if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
 150                count = refill_free_cache(sb);
 151                if (count == 0) {
 152                        iput(inode);
 153                        unlock_super(sb);
 154                        return ERR_PTR(-ENOSPC);
 155                }
 156        }
 157        /* Now count > 0. */
 158        ino = *sv_sb_fic_inode(sb,--count);
 159        *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count);
 160        fs16_add(sbi, sbi->s_sb_total_free_inodes, -1);
 161        dirty_sb(sb);
 162        
 163        if (dir->i_mode & S_ISGID) {
 164                inode->i_gid = dir->i_gid;
 165                if (S_ISDIR(mode))
 166                        mode |= S_ISGID;
 167        } else
 168                inode->i_gid = current_fsgid();
 169
 170        inode->i_uid = current_fsuid();
 171        inode->i_ino = fs16_to_cpu(sbi, ino);
 172        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 173        inode->i_blocks = 0;
 174        memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
 175        SYSV_I(inode)->i_dir_start_lookup = 0;
 176        insert_inode_hash(inode);
 177        mark_inode_dirty(inode);
 178
 179        inode->i_mode = mode;           /* for sysv_write_inode() */
 180        sysv_write_inode(inode, 0);     /* ensure inode not allocated again */
 181        mark_inode_dirty(inode);        /* cleared by sysv_write_inode() */
 182        /* That's it. */
 183        unlock_super(sb);
 184        return inode;
 185}
 186
 187unsigned long sysv_count_free_inodes(struct super_block * sb)
 188{
 189        struct sysv_sb_info *sbi = SYSV_SB(sb);
 190        struct buffer_head * bh;
 191        struct sysv_inode * raw_inode;
 192        int ino, count, sb_count;
 193
 194        lock_super(sb);
 195
 196        sb_count = fs16_to_cpu(sbi, *sbi->s_sb_total_free_inodes);
 197
 198        if (0)
 199                goto trust_sb;
 200
 201        /* this causes a lot of disk traffic ... */
 202        count = 0;
 203        ino = SYSV_ROOT_INO+1;
 204        raw_inode = sysv_raw_inode(sb, ino, &bh);
 205        if (!raw_inode)
 206                goto Eio;
 207        while (ino <= sbi->s_ninodes) {
 208                if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
 209                        count++;
 210                if ((ino++ & sbi->s_inodes_per_block_1) == 0) {
 211                        brelse(bh);
 212                        raw_inode = sysv_raw_inode(sb, ino, &bh);
 213                        if (!raw_inode)
 214                                goto Eio;
 215                } else
 216                        raw_inode++;
 217        }
 218        brelse(bh);
 219        if (count != sb_count)
 220                goto Einval;
 221out:
 222        unlock_super(sb);
 223        return count;
 224
 225Einval:
 226        printk("sysv_count_free_inodes: "
 227                "free inode count was %d, correcting to %d\n",
 228                sb_count, count);
 229        if (!(sb->s_flags & MS_RDONLY)) {
 230                *sbi->s_sb_total_free_inodes = cpu_to_fs16(SYSV_SB(sb), count);
 231                dirty_sb(sb);
 232        }
 233        goto out;
 234
 235Eio:
 236        printk("sysv_count_free_inodes: unable to read inode table\n");
 237trust_sb:
 238        count = sb_count;
 239        goto out;
 240}
 241