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

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