root/fs/ext2/inode.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext2_put_inode
  2. block_bmap
  3. ext2_bmap
  4. inode_getblk
  5. block_getblk
  6. ext2_getblk
  7. ext2_bread
  8. ext2_read_inode
  9. ext2_update_inode
  10. ext2_write_inode
  11. ext2_sync_inode

   1 /*
   2  *  linux/fs/ext2/inode.c
   3  *
   4  *  Copyright (C) 1992, 1993  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  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  13  */
  14 
  15 #include <asm/segment.h>
  16 #include <asm/system.h>
  17 
  18 #include <linux/errno.h>
  19 #include <linux/fs.h>
  20 #include <linux/ext2_fs.h>
  21 #include <linux/kernel.h>
  22 #include <linux/sched.h>
  23 #include <linux/stat.h>
  24 #include <linux/string.h>
  25 #include <linux/locks.h>
  26 
  27 void ext2_put_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO ||
  30             inode->i_ino == EXT2_ACL_DATA_INO)
  31                 return;
  32         inode->i_size = 0;
  33         if (inode->i_blocks)
  34                 ext2_truncate (inode);
  35         ext2_free_inode (inode);
  36 }
  37 
  38 #define inode_bmap(inode, nr) ((inode)->u.ext2_i.i_data[(nr)])
  39 
  40 static int block_bmap (struct buffer_head * bh, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         int tmp;
  43 
  44         if (!bh)
  45                 return 0;
  46         tmp = ((unsigned long *) bh->b_data)[nr];
  47         brelse (bh);
  48         return tmp;
  49 }
  50 
  51 int ext2_bmap (struct inode * inode, int block)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53         int i;
  54         int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
  55 
  56         if (block < 0) {
  57                 ext2_warning (inode->i_sb, "ext2_bmap", "block < 0");
  58                 return 0;
  59         }
  60         if (block >= EXT2_NDIR_BLOCKS + addr_per_block +
  61                      addr_per_block * addr_per_block +
  62                      addr_per_block * addr_per_block * addr_per_block) {
  63                 ext2_warning (inode->i_sb, "ext2_bmap", "block > big");
  64                 return 0;
  65         }
  66         if (block < EXT2_NDIR_BLOCKS)
  67                 return inode_bmap (inode, block);
  68         block -= EXT2_NDIR_BLOCKS;
  69         if (block < addr_per_block) {
  70                 i = inode_bmap (inode, EXT2_IND_BLOCK);
  71                 if (!i)
  72                         return 0;
  73                 return block_bmap (bread (inode->i_dev, i,
  74                                           inode->i_sb->s_blocksize), block);
  75         }
  76         block -= addr_per_block;
  77         if (block < addr_per_block * addr_per_block) {
  78                 i = inode_bmap (inode, EXT2_DIND_BLOCK);
  79                 if (!i)
  80                         return 0;
  81                 i = block_bmap (bread (inode->i_dev, i,
  82                                        inode->i_sb->s_blocksize),
  83                                 block / addr_per_block);
  84                 if (!i)
  85                         return 0;
  86                 return block_bmap (bread (inode->i_dev, i,
  87                                           inode->i_sb->s_blocksize),
  88                                    block & (addr_per_block - 1));
  89         }
  90         block -= addr_per_block * addr_per_block;
  91         i = inode_bmap (inode, EXT2_TIND_BLOCK);
  92         if (!i)
  93                 return 0;
  94         i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
  95                         block / (addr_per_block * addr_per_block));
  96         if (!i)
  97                 return 0;
  98         i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
  99                         (block / addr_per_block) & (addr_per_block - 1));
 100         if (!i)
 101                 return 0;
 102         return block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
 103                            block & (addr_per_block - 1));
 104 }
 105 
 106 static struct buffer_head * inode_getblk (struct inode * inode, int nr,
     /* [previous][next][first][last][top][bottom][index][help] */
 107                                           int create, int new_block, int * err)
 108 {
 109         int tmp, goal = 0;
 110         unsigned long * p;
 111         struct buffer_head * result;
 112         int blocks = inode->i_sb->s_blocksize / 512;
 113 
 114         p = inode->u.ext2_i.i_data + nr;
 115 repeat:
 116         tmp = *p;
 117         if (tmp) {
 118                 result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize);
 119                 if (tmp == *p)
 120                         return result;
 121                 brelse (result);
 122                 goto repeat;
 123         }
 124         if (!create || new_block >= 
 125             (current->rlim[RLIMIT_FSIZE].rlim_cur >>
 126              EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
 127                 *err = -EFBIG;
 128                 return NULL;
 129         }
 130         if (inode->u.ext2_i.i_next_alloc_block == new_block)
 131                 goal = inode->u.ext2_i.i_next_alloc_goal;
 132 
 133         ext2_debug ("hint = %d,", goal);
 134 
 135         if (!goal) {
 136                 for (tmp = nr - 1; tmp >= 0; tmp--) {
 137                         if (inode->u.ext2_i.i_data[tmp]) {
 138                                 goal = inode->u.ext2_i.i_data[tmp];
 139                                 break;
 140                         }
 141                 }
 142                 if (!goal)
 143                         goal = (inode->u.ext2_i.i_block_group * 
 144                                 EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
 145                                inode->i_sb->u.ext2_sb.s_es->s_first_data_block;
 146         }
 147 
 148         ext2_debug ("goal = %d.\n", goal);
 149 
 150         tmp = ext2_new_block (inode->i_sb, goal);
 151         if (!tmp)
 152                 return NULL;
 153         result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize);
 154         if (*p) {
 155                 ext2_free_block (inode->i_sb, tmp);
 156                 brelse (result);
 157                 goto repeat;
 158         }
 159         *p = tmp;
 160         inode->u.ext2_i.i_next_alloc_block = new_block;
 161         inode->u.ext2_i.i_next_alloc_goal = tmp;
 162         inode->i_ctime = CURRENT_TIME;
 163         inode->i_blocks += blocks;
 164         if (IS_SYNC(inode))
 165                 ext2_sync_inode (inode);
 166         else
 167                 inode->i_dirt = 1;
 168         return result;
 169 }
 170 
 171 static struct buffer_head * block_getblk (struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 172                                           struct buffer_head * bh, int nr,
 173                                           int create, int blocksize, 
 174                                           int new_block, int * err)
 175 {
 176         int tmp, goal = 0;
 177         unsigned long * p;
 178         struct buffer_head * result;
 179         int blocks = inode->i_sb->s_blocksize / 512;
 180 
 181         if (!bh)
 182                 return NULL;
 183         if (!bh->b_uptodate) {
 184                 ll_rw_block (READ, 1, &bh);
 185                 wait_on_buffer (bh);
 186                 if (!bh->b_uptodate) {
 187                         brelse (bh);
 188                         return NULL;
 189                 }
 190         }
 191         p = (unsigned long *) bh->b_data + nr;
 192 repeat:
 193         tmp = *p;
 194         if (tmp) {
 195                 result = getblk (bh->b_dev, tmp, blocksize);
 196                 if (tmp == *p) {
 197                         brelse (bh);
 198                         return result;
 199                 }
 200                 brelse (result);
 201                 goto repeat;
 202         }
 203         if (!create || new_block >= 
 204             (current->rlim[RLIMIT_FSIZE].rlim_cur >> 
 205              EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
 206                 brelse (bh);
 207                 *err = -EFBIG;
 208                 return NULL;
 209         }
 210         if (inode->u.ext2_i.i_next_alloc_block == new_block)
 211                 goal = inode->u.ext2_i.i_next_alloc_goal;
 212         if (!goal) {
 213                 for (tmp = nr - 1; tmp >= 0; tmp--) {
 214                         if (((unsigned long *) bh->b_data)[tmp]) {
 215                                 goal = ((unsigned long *)bh->b_data)[tmp];
 216                                 break;
 217                         }
 218                 }
 219                 if (!goal)
 220                         goal = bh->b_blocknr + 1;
 221         }
 222         tmp = ext2_new_block (inode->i_sb, goal);
 223         if (!tmp) {
 224                 brelse (bh);
 225                 return NULL;
 226         }
 227         result = getblk (bh->b_dev, tmp, blocksize);
 228         if (*p) {
 229                 ext2_free_block (inode->i_sb, tmp);
 230                 brelse (result);
 231                 goto repeat;
 232         }
 233         *p = tmp;
 234         bh->b_dirt = 1;
 235         if (IS_SYNC(inode)) {
 236                 ll_rw_block (WRITE, 1, &bh);
 237                 wait_on_buffer (bh);
 238         }
 239         inode->i_ctime = CURRENT_TIME;
 240         inode->i_blocks += blocks;
 241         inode->i_dirt = 1;
 242         inode->u.ext2_i.i_next_alloc_block = new_block;
 243         inode->u.ext2_i.i_next_alloc_goal = tmp;
 244         brelse (bh);
 245         return result;
 246 }
 247 
 248 struct buffer_head * ext2_getblk (struct inode * inode, long block,
     /* [previous][next][first][last][top][bottom][index][help] */
 249                                   int create, int * err)
 250 {
 251         struct buffer_head * bh;
 252         unsigned long b;
 253         unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 254 
 255         *err = -EIO;
 256         if (block < 0) {
 257                 ext2_warning (inode->i_sb, "ext2_getblk", "block < 0");
 258                 return NULL;
 259         }
 260         if (block > EXT2_NDIR_BLOCKS + addr_per_block  +
 261                     addr_per_block * addr_per_block +
 262                     addr_per_block * addr_per_block * addr_per_block) {
 263                 ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
 264                 return NULL;
 265         }
 266         /* If this is a sequential block allocation, set the next_alloc_block
 267            to this block now so that all the indblock and data block
 268            allocations use the same goal zone */
 269 
 270         ext2_debug ("block %lu, next %lu, goal %lu.\n", block, 
 271                     inode->u.ext2_i.i_next_alloc_block,
 272                     inode->u.ext2_i.i_next_alloc_goal);
 273 
 274         if (block == inode->u.ext2_i.i_next_alloc_block + 1) {
 275                 inode->u.ext2_i.i_next_alloc_block++;
 276                 inode->u.ext2_i.i_next_alloc_goal++;
 277         }
 278 
 279         *err = -ENOSPC;
 280         b = block;
 281         if (block < EXT2_NDIR_BLOCKS)
 282                 return inode_getblk (inode, block, create, b, err);
 283         block -= EXT2_NDIR_BLOCKS;
 284         if (block < addr_per_block) {
 285                 bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, err);
 286                 return block_getblk (inode, bh, block, create,
 287                                      inode->i_sb->s_blocksize, b, err);
 288         }
 289         block -= addr_per_block;
 290         if (block < addr_per_block * addr_per_block) {
 291                 bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, err);
 292                 bh = block_getblk (inode, bh, block / addr_per_block, create,
 293                                    inode->i_sb->s_blocksize, b, err);
 294                 return block_getblk (inode, bh, block & (addr_per_block - 1),
 295                                      create, inode->i_sb->s_blocksize, b, err);
 296         }
 297         block -= addr_per_block * addr_per_block;
 298         bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, err);
 299         bh = block_getblk (inode, bh, block/(addr_per_block * addr_per_block),
 300                            create, inode->i_sb->s_blocksize, b, err);
 301         bh = block_getblk (inode, bh, (block/addr_per_block) & (addr_per_block - 1),
 302                            create, inode->i_sb->s_blocksize, b, err);
 303         return block_getblk (inode, bh, block & (addr_per_block - 1), create,
 304                              inode->i_sb->s_blocksize, b, err);
 305 }
 306 
 307 struct buffer_head * ext2_bread (struct inode * inode, int block, 
     /* [previous][next][first][last][top][bottom][index][help] */
 308                                  int create, int *err)
 309 {
 310         struct buffer_head * bh;
 311 
 312         bh = ext2_getblk (inode, block, create, err);
 313         if (!bh || bh->b_uptodate)
 314                 return bh;
 315         ll_rw_block (READ, 1, &bh);
 316         wait_on_buffer (bh);
 317         if (bh->b_uptodate)
 318                 return bh;
 319         brelse (bh);
 320         *err = -EIO;
 321         return NULL;
 322 }
 323 
 324 void ext2_read_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326         struct buffer_head * bh;
 327         struct ext2_inode * raw_inode;
 328         unsigned long block_group;
 329         unsigned long group_desc;
 330         unsigned long desc;
 331         unsigned long block;
 332         struct ext2_group_desc * gdp;
 333 
 334         if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
 335              inode->i_ino != EXT2_ACL_DATA_INO && inode->i_ino < EXT2_FIRST_INO) ||
 336             inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
 337                 ext2_error (inode->i_sb, "ext2_read_inode",
 338                             "bad inode number: %lu", inode->i_ino);
 339                 return;
 340         }
 341         block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
 342         if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
 343                 ext2_panic (inode->i_sb, "ext2_read_inode",
 344                             "group >= groups count");
 345         group_desc = block_group / EXT2_DESC_PER_BLOCK(inode->i_sb);
 346         desc = block_group % EXT2_DESC_PER_BLOCK(inode->i_sb);
 347         bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
 348         if (!bh)
 349                 ext2_panic (inode->i_sb, "ext2_read_inode",
 350                             "Descriptor not loaded");
 351         gdp = (struct ext2_group_desc *) bh->b_data;
 352         block = gdp[desc].bg_inode_table +
 353                 (((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb))
 354                  / EXT2_INODES_PER_BLOCK(inode->i_sb));
 355         if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
 356                 ext2_panic (inode->i_sb, "ext2_read_inode",
 357                             "unable to read i-node block\n"
 358                             "inode=%lu, block=%lu", inode->i_ino, block);
 359         raw_inode = ((struct ext2_inode *) bh->b_data) +
 360                 (inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
 361         inode->i_mode = raw_inode->i_mode;
 362         inode->i_uid = raw_inode->i_uid;
 363         inode->i_gid = raw_inode->i_gid;
 364         inode->i_nlink = raw_inode->i_links_count;
 365         inode->i_size = raw_inode->i_size;
 366         inode->i_atime = raw_inode->i_atime;
 367         inode->i_ctime = raw_inode->i_ctime;
 368         inode->i_mtime = raw_inode->i_mtime;
 369         inode->u.ext2_i.i_dtime = raw_inode->i_dtime;
 370         inode->i_blksize = inode->i_sb->s_blocksize;
 371         inode->i_blocks = raw_inode->i_blocks;
 372         inode->u.ext2_i.i_flags = raw_inode->i_flags;
 373         inode->u.ext2_i.i_faddr = raw_inode->i_faddr;
 374         inode->u.ext2_i.i_frag = raw_inode->i_frag;
 375         inode->u.ext2_i.i_fsize = raw_inode->i_fsize;
 376         inode->u.ext2_i.i_file_acl = raw_inode->i_file_acl;
 377         inode->u.ext2_i.i_dir_acl = raw_inode->i_dir_acl;
 378         inode->u.ext2_i.i_version = raw_inode->i_version;
 379         inode->u.ext2_i.i_block_group = block_group;
 380         inode->u.ext2_i.i_next_alloc_block = 0;
 381         inode->u.ext2_i.i_next_alloc_goal = 0;
 382         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 383                 inode->i_rdev = raw_inode->i_block[0];
 384         else for (block = 0; block < EXT2_N_BLOCKS; block++)
 385                 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
 386         brelse (bh);
 387         inode->i_op = NULL;
 388         if (inode->i_ino == EXT2_ACL_IDX_INO ||
 389             inode->i_ino == EXT2_ACL_DATA_INO)
 390                 /* Nothing to do */ ;
 391         else if (S_ISREG(inode->i_mode))
 392                 inode->i_op = &ext2_file_inode_operations;
 393         else if (S_ISDIR(inode->i_mode))
 394                 inode->i_op = &ext2_dir_inode_operations;
 395         else if (S_ISLNK(inode->i_mode))
 396                 inode->i_op = &ext2_symlink_inode_operations;
 397         else if (S_ISCHR(inode->i_mode))
 398                 inode->i_op = &chrdev_inode_operations;
 399         else if (S_ISBLK(inode->i_mode))
 400                 inode->i_op = &blkdev_inode_operations;
 401         else if (S_ISFIFO(inode->i_mode))
 402                 init_fifo(inode);
 403         if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
 404                 inode->i_flags |= MS_SYNC;
 405 }
 406 
 407 static struct buffer_head * ext2_update_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 408 {
 409         struct buffer_head * bh;
 410         struct ext2_inode * raw_inode;
 411         unsigned long block_group;
 412         unsigned long group_desc;
 413         unsigned long desc;
 414         unsigned long block;
 415         struct ext2_group_desc * gdp;
 416 
 417         if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino < EXT2_FIRST_INO) ||
 418             inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
 419                 ext2_error (inode->i_sb, "ext2_write_inode",
 420                             "bad inode number: %lu", inode->i_ino);
 421                 return 0;
 422         }
 423         block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
 424         if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
 425                 ext2_panic (inode->i_sb, "ext2_write_inode",
 426                             "group >= groups count");
 427         group_desc = block_group / EXT2_DESC_PER_BLOCK(inode->i_sb);
 428         desc = block_group % EXT2_DESC_PER_BLOCK(inode->i_sb);
 429         bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
 430         if (!bh)
 431                 ext2_panic (inode->i_sb, "ext2_write_inode",
 432                             "Descriptor not loaded");
 433         gdp = (struct ext2_group_desc *) bh->b_data;
 434         block = gdp[desc].bg_inode_table +
 435                 (((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb))
 436                  / EXT2_INODES_PER_BLOCK(inode->i_sb));
 437         if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
 438                 ext2_panic (inode->i_sb, "ext2_write_inode",
 439                             "unable to read i-node block\n"
 440                             "inode=%lu, block=%lu", inode->i_ino, block);
 441         raw_inode = ((struct ext2_inode *)bh->b_data) +
 442                 (inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
 443         raw_inode->i_mode = inode->i_mode;
 444         raw_inode->i_uid = inode->i_uid;
 445         raw_inode->i_gid = inode->i_gid;
 446         raw_inode->i_links_count = inode->i_nlink;
 447         raw_inode->i_size = inode->i_size;
 448         raw_inode->i_atime = inode->i_atime;
 449         raw_inode->i_ctime = inode->i_ctime;
 450         raw_inode->i_mtime = inode->i_mtime;
 451         raw_inode->i_blocks = inode->i_blocks;
 452         raw_inode->i_dtime = inode->u.ext2_i.i_dtime;
 453         raw_inode->i_flags = inode->u.ext2_i.i_flags;
 454         raw_inode->i_faddr = inode->u.ext2_i.i_faddr;
 455         raw_inode->i_frag = inode->u.ext2_i.i_frag;
 456         raw_inode->i_fsize = inode->u.ext2_i.i_fsize;
 457         raw_inode->i_file_acl = inode->u.ext2_i.i_file_acl;
 458         raw_inode->i_dir_acl = inode->u.ext2_i.i_dir_acl;
 459         raw_inode->i_version = inode->u.ext2_i.i_version;
 460         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 461                 raw_inode->i_block[0] = inode->i_rdev;
 462         else for (block = 0; block < EXT2_N_BLOCKS; block++)
 463                 raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
 464         bh->b_dirt = 1;
 465         inode->i_dirt = 0;
 466         return bh;
 467 }
 468 
 469 void ext2_write_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 470 {
 471         struct buffer_head * bh;
 472         bh = ext2_update_inode (inode);
 473         brelse (bh);
 474 }
 475 
 476 int ext2_sync_inode (struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 477 {
 478         int err = 0;
 479         struct buffer_head *bh;
 480 
 481         bh = ext2_update_inode (inode);
 482         if (bh && bh->b_dirt)
 483         {
 484                 ll_rw_block (WRITE, 1, &bh);
 485                 wait_on_buffer (bh);
 486                 if (bh->b_req && !bh->b_uptodate)
 487                 {
 488                         printk ("IO error syncing ext2 inode [%04x:%08lx]\n",
 489                                 inode->i_dev, inode->i_ino);
 490                         err = -1;
 491                 }
 492         }
 493         else if (!bh)
 494                 err = -1;
 495         brelse (bh);
 496         return err;
 497 }

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