linux/fs/sysv/inode.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/sysv/inode.c
   3 *
   4 *  minix/inode.c
   5 *  Copyright (C) 1991, 1992  Linus Torvalds
   6 *
   7 *  xenix/inode.c
   8 *  Copyright (C) 1992  Doug Evans
   9 *
  10 *  coh/inode.c
  11 *  Copyright (C) 1993  Pascal Haible, Bruno Haible
  12 *
  13 *  sysv/inode.c
  14 *  Copyright (C) 1993  Paul B. Monday
  15 *
  16 *  sysv/inode.c
  17 *  Copyright (C) 1993  Bruno Haible
  18 *  Copyright (C) 1997, 1998  Krzysztof G. Baranowski
  19 *
  20 *  This file contains code for allocating/freeing inodes and for read/writing
  21 *  the superblock.
  22 */
  23
  24#include <linux/highuid.h>
  25#include <linux/slab.h>
  26#include <linux/init.h>
  27#include <linux/buffer_head.h>
  28#include <linux/vfs.h>
  29#include <linux/writeback.h>
  30#include <linux/namei.h>
  31#include <asm/byteorder.h>
  32#include "sysv.h"
  33
  34static int sysv_sync_fs(struct super_block *sb, int wait)
  35{
  36        struct sysv_sb_info *sbi = SYSV_SB(sb);
  37        unsigned long time = get_seconds(), old_time;
  38
  39        mutex_lock(&sbi->s_lock);
  40
  41        /*
  42         * If we are going to write out the super block,
  43         * then attach current time stamp.
  44         * But if the filesystem was marked clean, keep it clean.
  45         */
  46        old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
  47        if (sbi->s_type == FSTYPE_SYSV4) {
  48                if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
  49                        *sbi->s_sb_state = cpu_to_fs32(sbi, 0x7c269d38 - time);
  50                *sbi->s_sb_time = cpu_to_fs32(sbi, time);
  51                mark_buffer_dirty(sbi->s_bh2);
  52        }
  53
  54        mutex_unlock(&sbi->s_lock);
  55
  56        return 0;
  57}
  58
  59static int sysv_remount(struct super_block *sb, int *flags, char *data)
  60{
  61        struct sysv_sb_info *sbi = SYSV_SB(sb);
  62
  63        if (sbi->s_forced_ro)
  64                *flags |= MS_RDONLY;
  65        return 0;
  66}
  67
  68static void sysv_put_super(struct super_block *sb)
  69{
  70        struct sysv_sb_info *sbi = SYSV_SB(sb);
  71
  72        if (!(sb->s_flags & MS_RDONLY)) {
  73                /* XXX ext2 also updates the state here */
  74                mark_buffer_dirty(sbi->s_bh1);
  75                if (sbi->s_bh1 != sbi->s_bh2)
  76                        mark_buffer_dirty(sbi->s_bh2);
  77        }
  78
  79        brelse(sbi->s_bh1);
  80        if (sbi->s_bh1 != sbi->s_bh2)
  81                brelse(sbi->s_bh2);
  82
  83        kfree(sbi);
  84}
  85
  86static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
  87{
  88        struct super_block *sb = dentry->d_sb;
  89        struct sysv_sb_info *sbi = SYSV_SB(sb);
  90        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
  91
  92        buf->f_type = sb->s_magic;
  93        buf->f_bsize = sb->s_blocksize;
  94        buf->f_blocks = sbi->s_ndatazones;
  95        buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb);
  96        buf->f_files = sbi->s_ninodes;
  97        buf->f_ffree = sysv_count_free_inodes(sb);
  98        buf->f_namelen = SYSV_NAMELEN;
  99        buf->f_fsid.val[0] = (u32)id;
 100        buf->f_fsid.val[1] = (u32)(id >> 32);
 101        return 0;
 102}
 103
 104/* 
 105 * NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32
 106 */
 107static inline void read3byte(struct sysv_sb_info *sbi,
 108        unsigned char * from, unsigned char * to)
 109{
 110        if (sbi->s_bytesex == BYTESEX_PDP) {
 111                to[0] = from[0];
 112                to[1] = 0;
 113                to[2] = from[1];
 114                to[3] = from[2];
 115        } else if (sbi->s_bytesex == BYTESEX_LE) {
 116                to[0] = from[0];
 117                to[1] = from[1];
 118                to[2] = from[2];
 119                to[3] = 0;
 120        } else {
 121                to[0] = 0;
 122                to[1] = from[0];
 123                to[2] = from[1];
 124                to[3] = from[2];
 125        }
 126}
 127
 128static inline void write3byte(struct sysv_sb_info *sbi,
 129        unsigned char * from, unsigned char * to)
 130{
 131        if (sbi->s_bytesex == BYTESEX_PDP) {
 132                to[0] = from[0];
 133                to[1] = from[2];
 134                to[2] = from[3];
 135        } else if (sbi->s_bytesex == BYTESEX_LE) {
 136                to[0] = from[0];
 137                to[1] = from[1];
 138                to[2] = from[2];
 139        } else {
 140                to[0] = from[1];
 141                to[1] = from[2];
 142                to[2] = from[3];
 143        }
 144}
 145
 146static const struct inode_operations sysv_symlink_inode_operations = {
 147        .readlink       = generic_readlink,
 148        .follow_link    = page_follow_link_light,
 149        .put_link       = page_put_link,
 150        .getattr        = sysv_getattr,
 151};
 152
 153void sysv_set_inode(struct inode *inode, dev_t rdev)
 154{
 155        if (S_ISREG(inode->i_mode)) {
 156                inode->i_op = &sysv_file_inode_operations;
 157                inode->i_fop = &sysv_file_operations;
 158                inode->i_mapping->a_ops = &sysv_aops;
 159        } else if (S_ISDIR(inode->i_mode)) {
 160                inode->i_op = &sysv_dir_inode_operations;
 161                inode->i_fop = &sysv_dir_operations;
 162                inode->i_mapping->a_ops = &sysv_aops;
 163        } else if (S_ISLNK(inode->i_mode)) {
 164                if (inode->i_blocks) {
 165                        inode->i_op = &sysv_symlink_inode_operations;
 166                        inode->i_mapping->a_ops = &sysv_aops;
 167                } else {
 168                        inode->i_op = &sysv_fast_symlink_inode_operations;
 169                        nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size,
 170                                sizeof(SYSV_I(inode)->i_data) - 1);
 171                }
 172        } else
 173                init_special_inode(inode, inode->i_mode, rdev);
 174}
 175
 176struct inode *sysv_iget(struct super_block *sb, unsigned int ino)
 177{
 178        struct sysv_sb_info * sbi = SYSV_SB(sb);
 179        struct buffer_head * bh;
 180        struct sysv_inode * raw_inode;
 181        struct sysv_inode_info * si;
 182        struct inode *inode;
 183        unsigned int block;
 184
 185        if (!ino || ino > sbi->s_ninodes) {
 186                printk("Bad inode number on dev %s: %d is out of range\n",
 187                       sb->s_id, ino);
 188                return ERR_PTR(-EIO);
 189        }
 190
 191        inode = iget_locked(sb, ino);
 192        if (!inode)
 193                return ERR_PTR(-ENOMEM);
 194        if (!(inode->i_state & I_NEW))
 195                return inode;
 196
 197        raw_inode = sysv_raw_inode(sb, ino, &bh);
 198        if (!raw_inode) {
 199                printk("Major problem: unable to read inode from dev %s\n",
 200                       inode->i_sb->s_id);
 201                goto bad_inode;
 202        }
 203        /* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
 204        inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode);
 205        i_uid_write(inode, (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid));
 206        i_gid_write(inode, (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid));
 207        set_nlink(inode, fs16_to_cpu(sbi, raw_inode->i_nlink));
 208        inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
 209        inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime);
 210        inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime);
 211        inode->i_ctime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_ctime);
 212        inode->i_ctime.tv_nsec = 0;
 213        inode->i_atime.tv_nsec = 0;
 214        inode->i_mtime.tv_nsec = 0;
 215        inode->i_blocks = 0;
 216
 217        si = SYSV_I(inode);
 218        for (block = 0; block < 10+1+1+1; block++)
 219                read3byte(sbi, &raw_inode->i_data[3*block],
 220                                (u8 *)&si->i_data[block]);
 221        brelse(bh);
 222        si->i_dir_start_lookup = 0;
 223        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 224                sysv_set_inode(inode,
 225                               old_decode_dev(fs32_to_cpu(sbi, si->i_data[0])));
 226        else
 227                sysv_set_inode(inode, 0);
 228        unlock_new_inode(inode);
 229        return inode;
 230
 231bad_inode:
 232        iget_failed(inode);
 233        return ERR_PTR(-EIO);
 234}
 235
 236static int __sysv_write_inode(struct inode *inode, int wait)
 237{
 238        struct super_block * sb = inode->i_sb;
 239        struct sysv_sb_info * sbi = SYSV_SB(sb);
 240        struct buffer_head * bh;
 241        struct sysv_inode * raw_inode;
 242        struct sysv_inode_info * si;
 243        unsigned int ino, block;
 244        int err = 0;
 245
 246        ino = inode->i_ino;
 247        if (!ino || ino > sbi->s_ninodes) {
 248                printk("Bad inode number on dev %s: %d is out of range\n",
 249                       inode->i_sb->s_id, ino);
 250                return -EIO;
 251        }
 252        raw_inode = sysv_raw_inode(sb, ino, &bh);
 253        if (!raw_inode) {
 254                printk("unable to read i-node block\n");
 255                return -EIO;
 256        }
 257
 258        raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode);
 259        raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(i_uid_read(inode)));
 260        raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(i_gid_read(inode)));
 261        raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink);
 262        raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size);
 263        raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime.tv_sec);
 264        raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime.tv_sec);
 265        raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime.tv_sec);
 266
 267        si = SYSV_I(inode);
 268        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 269                si->i_data[0] = cpu_to_fs32(sbi, old_encode_dev(inode->i_rdev));
 270        for (block = 0; block < 10+1+1+1; block++)
 271                write3byte(sbi, (u8 *)&si->i_data[block],
 272                        &raw_inode->i_data[3*block]);
 273        mark_buffer_dirty(bh);
 274        if (wait) {
 275                sync_dirty_buffer(bh);
 276                if (buffer_req(bh) && !buffer_uptodate(bh)) {
 277                        printk ("IO error syncing sysv inode [%s:%08x]\n",
 278                                sb->s_id, ino);
 279                        err = -EIO;
 280                }
 281        }
 282        brelse(bh);
 283        return 0;
 284}
 285
 286int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
 287{
 288        return __sysv_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 289}
 290
 291int sysv_sync_inode(struct inode *inode)
 292{
 293        return __sysv_write_inode(inode, 1);
 294}
 295
 296static void sysv_evict_inode(struct inode *inode)
 297{
 298        truncate_inode_pages(&inode->i_data, 0);
 299        if (!inode->i_nlink) {
 300                inode->i_size = 0;
 301                sysv_truncate(inode);
 302        }
 303        invalidate_inode_buffers(inode);
 304        clear_inode(inode);
 305        if (!inode->i_nlink)
 306                sysv_free_inode(inode);
 307}
 308
 309static struct kmem_cache *sysv_inode_cachep;
 310
 311static struct inode *sysv_alloc_inode(struct super_block *sb)
 312{
 313        struct sysv_inode_info *si;
 314
 315        si = kmem_cache_alloc(sysv_inode_cachep, GFP_KERNEL);
 316        if (!si)
 317                return NULL;
 318        return &si->vfs_inode;
 319}
 320
 321static void sysv_i_callback(struct rcu_head *head)
 322{
 323        struct inode *inode = container_of(head, struct inode, i_rcu);
 324        kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
 325}
 326
 327static void sysv_destroy_inode(struct inode *inode)
 328{
 329        call_rcu(&inode->i_rcu, sysv_i_callback);
 330}
 331
 332static void init_once(void *p)
 333{
 334        struct sysv_inode_info *si = (struct sysv_inode_info *)p;
 335
 336        inode_init_once(&si->vfs_inode);
 337}
 338
 339const struct super_operations sysv_sops = {
 340        .alloc_inode    = sysv_alloc_inode,
 341        .destroy_inode  = sysv_destroy_inode,
 342        .write_inode    = sysv_write_inode,
 343        .evict_inode    = sysv_evict_inode,
 344        .put_super      = sysv_put_super,
 345        .sync_fs        = sysv_sync_fs,
 346        .remount_fs     = sysv_remount,
 347        .statfs         = sysv_statfs,
 348};
 349
 350int __init sysv_init_icache(void)
 351{
 352        sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
 353                        sizeof(struct sysv_inode_info), 0,
 354                        SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
 355                        init_once);
 356        if (!sysv_inode_cachep)
 357                return -ENOMEM;
 358        return 0;
 359}
 360
 361void sysv_destroy_icache(void)
 362{
 363        /*
 364         * Make sure all delayed rcu free inodes are flushed before we
 365         * destroy cache.
 366         */
 367        rcu_barrier();
 368        kmem_cache_destroy(sysv_inode_cachep);
 369}
 370
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.