root/fs/ext/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext_put_inode
  2. ext_put_super
  3. ext_read_super
  4. ext_write_super
  5. ext_statfs
  6. block_bmap
  7. ext_bmap
  8. inode_getblk
  9. block_getblk
  10. ext_getblk
  11. ext_bread
  12. ext_read_inode
  13. ext_write_inode

   1 /*
   2  *  linux/fs/ext/inode.c
   3  *
   4  *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
   5  *
   6  *  from
   7  *
   8  *  linux/fs/minix/inode.c
   9  *
  10  *  Copyright (C) 1991, 1992  Linus Torvalds
  11  */
  12 
  13 #include <linux/sched.h>
  14 #include <linux/ext_fs.h>
  15 #include <linux/kernel.h>
  16 #include <linux/mm.h>
  17 #include <linux/string.h>
  18 #include <linux/stat.h>
  19 #include <linux/locks.h>
  20 
  21 #include <asm/system.h>
  22 #include <asm/segment.h>
  23 
  24 void ext_put_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26         if (inode->i_nlink)
  27                 return;
  28         inode->i_size = 0;
  29         ext_truncate(inode);
  30         ext_free_inode(inode);
  31 }
  32 
  33 void ext_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35 
  36         lock_super(sb);
  37         sb->s_dev = 0;
  38         if (sb->u.ext_sb.s_firstfreeinodeblock)
  39                 brelse (sb->u.ext_sb.s_firstfreeinodeblock);
  40         if (sb->u.ext_sb.s_firstfreeblock)
  41                 brelse (sb->u.ext_sb.s_firstfreeblock);
  42         unlock_super(sb);
  43         return;
  44 }
  45 
  46 static struct super_operations ext_sops = { 
  47         ext_read_inode,
  48         NULL,
  49         ext_write_inode,
  50         ext_put_inode,
  51         ext_put_super,
  52         ext_write_super,
  53         ext_statfs
  54 };
  55 
  56 struct super_block *ext_read_super(struct super_block *s,void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         struct buffer_head *bh;
  59         struct ext_super_block *es;
  60         int dev = s->s_dev,block;
  61 
  62         lock_super(s);
  63         if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
  64                 s->s_dev=0;
  65                 unlock_super(s);
  66                 printk("EXT-fs: unable to read superblock\n");
  67                 return NULL;
  68         }
  69         es = (struct ext_super_block *) bh->b_data;
  70         s->s_blocksize = 1024;
  71         s->u.ext_sb.s_ninodes = es->s_ninodes;
  72         s->u.ext_sb.s_nzones = es->s_nzones;
  73         s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
  74         s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
  75         s->u.ext_sb.s_max_size = es->s_max_size;
  76         s->s_magic = es->s_magic;
  77         s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
  78         s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
  79         s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
  80         s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
  81         brelse(bh);
  82         if (s->s_magic != EXT_SUPER_MAGIC) {
  83                 s->s_dev = 0;
  84                 unlock_super(s);
  85                 printk("EXT-fs: magic match failed\n");
  86                 return NULL;
  87         }
  88         if (!s->u.ext_sb.s_firstfreeblocknumber)
  89                 s->u.ext_sb.s_firstfreeblock = NULL;
  90         else
  91                 if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
  92                         s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
  93                         printk("ext_read_super: unable to read first free block\n");
  94                         s->s_dev = 0;
  95                         unlock_super(s);
  96                         return NULL;
  97                 }
  98         if (!s->u.ext_sb.s_firstfreeinodenumber)
  99                 s->u.ext_sb.s_firstfreeinodeblock = NULL;
 100         else {
 101                 block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
 102                 if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
 103                         printk("ext_read_super: unable to read first free inode block\n");
 104                         brelse(s->u.ext_sb.s_firstfreeblock);
 105                         s->s_dev = 0;
 106                         unlock_super (s);
 107                         return NULL;
 108                 }
 109         }
 110         unlock_super(s);
 111         /* set up enough so that it can read an inode */
 112         s->s_dev = dev;
 113         s->s_op = &ext_sops;
 114         if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
 115                 s->s_dev=0;
 116                 printk("EXT-fs: get root inode failed\n");
 117                 return NULL;
 118         }
 119         return s;
 120 }
 121 
 122 void ext_write_super (struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         struct buffer_head * bh;
 125         struct ext_super_block * es;
 126 
 127         if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
 128                 printk ("ext_write_super: bread failed\n");
 129                 return;
 130         }
 131         es = (struct ext_super_block *) bh->b_data;
 132         es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
 133         es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
 134         es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
 135         es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
 136         bh->b_dirt = 1;
 137         brelse (bh);
 138         sb->s_dirt = 0;
 139 }
 140 
 141 void ext_statfs (struct super_block *sb, struct statfs *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         long tmp;
 144 
 145         put_fs_long(EXT_SUPER_MAGIC, &buf->f_type);
 146         put_fs_long(1024, &buf->f_bsize);
 147         put_fs_long(sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size,
 148                 &buf->f_blocks);
 149         tmp = ext_count_free_blocks(sb);
 150         put_fs_long(tmp, &buf->f_bfree);
 151         put_fs_long(tmp, &buf->f_bavail);
 152         put_fs_long(sb->u.ext_sb.s_ninodes, &buf->f_files);
 153         put_fs_long(ext_count_free_inodes(sb), &buf->f_ffree);
 154         /* Don't know what value to put in buf->f_fsid */
 155 }
 156 
 157 #define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
 158 
 159 static int block_bmap(struct buffer_head * bh, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int tmp;
 162 
 163         if (!bh)
 164                 return 0;
 165         tmp = ((unsigned long *) bh->b_data)[nr];
 166         brelse(bh);
 167         return tmp;
 168 }
 169 
 170 int ext_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int i;
 173 
 174         if (block<0) {
 175                 printk("ext_bmap: block<0");
 176                 return 0;
 177         }
 178         if (block >= 9+256+256*256+256*256*256) {
 179                 printk("ext_bmap: block>big");
 180                 return 0;
 181         }
 182         if (block<9)
 183                 return inode_bmap(inode,block);
 184         block -= 9;
 185         if (block<256) {
 186                 i = inode_bmap(inode,9);
 187                 if (!i)
 188                         return 0;
 189                 return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
 190         }
 191         block -= 256;
 192         if (block<256*256) {
 193                 i = inode_bmap(inode,10);
 194                 if (!i)
 195                         return 0;
 196                 i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
 197                 if (!i)
 198                         return 0;
 199                 return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
 200         }
 201         block -= 256*256;
 202         i = inode_bmap(inode,11);
 203         if (!i)
 204                 return 0;
 205         i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
 206         if (!i)
 207                 return 0;
 208         i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
 209         if (!i)
 210                 return 0;
 211         return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
 212 }
 213 
 214 static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216         int tmp;
 217         unsigned long * p;
 218         struct buffer_head * result;
 219 
 220         p = inode->u.ext_i.i_data + nr;
 221 repeat:
 222         tmp = *p;
 223         if (tmp) {
 224                 result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
 225                 if (tmp == *p)
 226                         return result;
 227                 brelse(result);
 228                 goto repeat;
 229         }
 230         if (!create)
 231                 return NULL;
 232         tmp = ext_new_block(inode->i_sb);
 233         if (!tmp)
 234                 return NULL;
 235         result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
 236         if (*p) {
 237                 ext_free_block(inode->i_sb,tmp);
 238                 brelse(result);
 239                 goto repeat;
 240         }
 241         *p = tmp;
 242         inode->i_ctime = CURRENT_TIME;
 243         inode->i_dirt = 1;
 244         return result;
 245 }
 246 
 247 static struct buffer_head * block_getblk(struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 248         struct buffer_head * bh, int nr, int create)
 249 {
 250         int tmp;
 251         unsigned long * p;
 252         struct buffer_head * result;
 253 
 254         if (!bh)
 255                 return NULL;
 256         if (!bh->b_uptodate) {
 257                 ll_rw_block(READ, 1, &bh);
 258                 wait_on_buffer(bh);
 259                 if (!bh->b_uptodate) {
 260                         brelse(bh);
 261                         return NULL;
 262                 }
 263         }
 264         p = nr + (unsigned long *) bh->b_data;
 265 repeat:
 266         tmp = *p;
 267         if (tmp) {
 268                 result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
 269                 if (tmp == *p) {
 270                         brelse(bh);
 271                         return result;
 272                 }
 273                 brelse(result);
 274                 goto repeat;
 275         }
 276         if (!create) {
 277                 brelse(bh);
 278                 return NULL;
 279         }
 280         tmp = ext_new_block(inode->i_sb);
 281         if (!tmp) {
 282                 brelse(bh);
 283                 return NULL;
 284         }
 285         result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
 286         if (*p) {
 287                 ext_free_block(inode->i_sb,tmp);
 288                 brelse(result);
 289                 goto repeat;
 290         }
 291         *p = tmp;
 292         bh->b_dirt = 1;
 293         brelse(bh);
 294         return result;
 295 }
 296 
 297 struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299         struct buffer_head * bh;
 300 
 301         if (block<0) {
 302                 printk("ext_getblk: block<0\n");
 303                 return NULL;
 304         }
 305         if (block >= 9+256+256*256+256*256*256) {
 306                 printk("ext_getblk: block>big\n");
 307                 return NULL;
 308         }
 309         if (block<9)
 310                 return inode_getblk(inode,block,create);
 311         block -= 9;
 312         if (block<256) {
 313                 bh = inode_getblk(inode,9,create);
 314                 return block_getblk(inode,bh,block,create);
 315         }
 316         block -= 256;
 317         if (block<256*256) {
 318                 bh = inode_getblk(inode,10,create);
 319                 bh = block_getblk(inode,bh,block>>8,create);
 320                 return block_getblk(inode,bh,block & 255,create);
 321         }
 322         block -= 256*256;
 323         bh = inode_getblk(inode,11,create);
 324         bh = block_getblk(inode,bh,block>>16,create);
 325         bh = block_getblk(inode,bh,(block>>8) & 255,create);
 326         return block_getblk(inode,bh,block & 255,create);
 327 }
 328 
 329 struct buffer_head * ext_bread(struct inode * inode, int block, int create)
     /* [previous][next][first][last][top][bottom][index][help] */
 330 {
 331         struct buffer_head * bh;
 332 
 333         bh = ext_getblk(inode,block,create);
 334         if (!bh || bh->b_uptodate) 
 335                 return bh;
 336         ll_rw_block(READ, 1, &bh);
 337         wait_on_buffer(bh);
 338         if (bh->b_uptodate)
 339                 return bh;
 340         brelse(bh);
 341         return NULL;
 342 }
 343 
 344 void ext_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 345 {
 346         struct buffer_head * bh;
 347         struct ext_inode * raw_inode;
 348         int block;
 349 
 350         block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 351         if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 352                 panic("unable to read i-node block");
 353         raw_inode = ((struct ext_inode *) bh->b_data) +
 354                 (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
 355         inode->i_mode = raw_inode->i_mode;
 356         inode->i_uid = raw_inode->i_uid;
 357         inode->i_gid = raw_inode->i_gid;
 358         inode->i_nlink = raw_inode->i_nlinks;
 359         inode->i_size = raw_inode->i_size;
 360         inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
 361         inode->i_blocks = inode->i_blksize = 0;
 362         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 363                 inode->i_rdev = raw_inode->i_zone[0];
 364         else for (block = 0; block < 12; block++)
 365                 inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
 366         brelse(bh);
 367         inode->i_op = NULL;
 368         if (S_ISREG(inode->i_mode))
 369                 inode->i_op = &ext_file_inode_operations;
 370         else if (S_ISDIR(inode->i_mode))
 371                 inode->i_op = &ext_dir_inode_operations;
 372         else if (S_ISLNK(inode->i_mode))
 373                 inode->i_op = &ext_symlink_inode_operations;
 374         else if (S_ISCHR(inode->i_mode))
 375                 inode->i_op = &ext_chrdev_inode_operations;
 376         else if (S_ISBLK(inode->i_mode))
 377                 inode->i_op = &ext_blkdev_inode_operations;
 378         else if (S_ISFIFO(inode->i_mode)) {
 379                 inode->i_op = &ext_fifo_inode_operations;
 380                 inode->i_pipe = 1;
 381                 PIPE_BASE(*inode) = NULL;
 382                 PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
 383                 PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
 384                 PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
 385         }
 386 }
 387 
 388 void ext_write_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         struct buffer_head * bh;
 391         struct ext_inode * raw_inode;
 392         int block;
 393 
 394         block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
 395         if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
 396                 panic("unable to read i-node block");
 397         raw_inode = ((struct ext_inode *)bh->b_data) +
 398                 (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
 399         raw_inode->i_mode = inode->i_mode;
 400         raw_inode->i_uid = inode->i_uid;
 401         raw_inode->i_gid = inode->i_gid;
 402         raw_inode->i_nlinks = inode->i_nlink;
 403         raw_inode->i_size = inode->i_size;
 404         raw_inode->i_time = inode->i_mtime;
 405         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 406                 raw_inode->i_zone[0] = inode->i_rdev;
 407         else for (block = 0; block < 12; block++)
 408                 raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
 409         bh->b_dirt=1;
 410         inode->i_dirt=0;
 411         brelse(bh);
 412 }

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