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

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