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_discard_prealloc
  4. ext2_alloc_block
  5. ext2_bmap
  6. inode_getblk
  7. block_getblk
  8. block_getcluster
  9. ext2_getblk
  10. ext2_getcluster
  11. ext2_bread
  12. ext2_read_inode
  13. ext2_update_inode
  14. ext2_write_inode
  15. ext2_sync_inode

   1 /*
   2  *  linux/fs/ext2/inode.c
   3  *
   4  *  Copyright (C) 1992, 1993, 1994  Remy Card (card@masi.ibp.fr)
   5  *                                  Laboratoire MASI - Institut Blaise Pascal
   6  *                                  Universite Pierre et Marie Curie (Paris VI)
   7  *
   8  *  from
   9  *
  10  *  linux/fs/minix/inode.c
  11  *
  12  *  Copyright (C) 1991, 1992  Linus Torvalds
  13  *
  14  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  15  */
  16 
  17 #include <asm/segment.h>
  18 #include <asm/system.h>
  19 
  20 #include <linux/errno.h>
  21 #include <linux/fs.h>
  22 #include <linux/ext2_fs.h>
  23 #include <linux/sched.h>
  24 #include <linux/stat.h>
  25 #include <linux/string.h>
  26 #include <linux/locks.h>
  27 #include <linux/mm.h>
  28 
  29 void ext2_put_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         ext2_discard_prealloc (inode);
  32         if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO ||
  33             inode->i_ino == EXT2_ACL_DATA_INO)
  34                 return;
  35         inode->i_size = 0;
  36         if (inode->i_blocks)
  37                 ext2_truncate (inode);
  38         ext2_free_inode (inode);
  39 }
  40 
  41 #define inode_bmap(inode, nr) ((inode)->u.ext2_i.i_data[(nr)])
  42 
  43 static int block_bmap (struct buffer_head * bh, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         int tmp;
  46 
  47         if (!bh)
  48                 return 0;
  49         tmp = ((unsigned long *) bh->b_data)[nr];
  50         brelse (bh);
  51         return tmp;
  52 }
  53 
  54 /* 
  55  * ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the
  56  * superblock in the same manner as are ext2_free_blocks and
  57  * ext2_new_block.  We just wait on the super rather than locking it
  58  * here, since ext2_new_block will do the necessary locking and we
  59  * can't block until then.
  60  */
  61 void ext2_discard_prealloc (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63 #ifdef EXT2_PREALLOCATE
  64         if (inode->u.ext2_i.i_prealloc_count) {
  65                 int i = inode->u.ext2_i.i_prealloc_count;
  66                 inode->u.ext2_i.i_prealloc_count = 0;
  67                 ext2_free_blocks (inode->i_sb,
  68                                   inode->u.ext2_i.i_prealloc_block,
  69                                   i);
  70         }
  71 #endif
  72 }
  73 
  74 static int ext2_alloc_block (struct inode * inode, unsigned long goal)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76 #ifdef EXT2FS_DEBUG
  77         static unsigned long alloc_hits = 0, alloc_attempts = 0;
  78 #endif
  79         unsigned long result;
  80         struct buffer_head * bh;
  81 
  82         wait_on_super (inode->i_sb);
  83 
  84 #ifdef EXT2_PREALLOCATE
  85         if (inode->u.ext2_i.i_prealloc_count &&
  86             (goal == inode->u.ext2_i.i_prealloc_block ||
  87              goal + 1 == inode->u.ext2_i.i_prealloc_block))
  88         {               
  89                 result = inode->u.ext2_i.i_prealloc_block++;
  90                 inode->u.ext2_i.i_prealloc_count--;
  91                 ext2_debug ("preallocation hit (%lu/%lu).\n",
  92                             ++alloc_hits, ++alloc_attempts);
  93 
  94                 /* It doesn't matter if we block in getblk() since
  95                    we have already atomically allocated the block, and
  96                    are only clearing it now. */
  97                 if (!(bh = getblk (inode->i_sb->s_dev, result,
  98                                    inode->i_sb->s_blocksize))) {
  99                         ext2_error (inode->i_sb, "ext2_alloc_block",
 100                                     "cannot get block %lu", result);
 101                         return 0;
 102                 }
 103                 memset(bh->b_data, 0, inode->i_sb->s_blocksize);
 104                 bh->b_uptodate = 1;
 105                 mark_buffer_dirty(bh, 1);
 106                 brelse (bh);
 107         } else {
 108                 ext2_discard_prealloc (inode);
 109                 ext2_debug ("preallocation miss (%lu/%lu).\n",
 110                             alloc_hits, ++alloc_attempts);
 111                 if (S_ISREG(inode->i_mode))
 112                         result = ext2_new_block
 113                                 (inode->i_sb, goal,
 114                                  &inode->u.ext2_i.i_prealloc_count,
 115                                  &inode->u.ext2_i.i_prealloc_block);
 116                 else
 117                         result = ext2_new_block (inode->i_sb, goal, 0, 0);
 118         }
 119 #else
 120         result = ext2_new_block (inode->i_sb, goal, 0, 0);
 121 #endif
 122 
 123         return result;
 124 }
 125 
 126 
 127 int ext2_bmap (struct inode * inode, int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         int i;
 130         int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 131 
 132         if (block < 0) {
 133                 ext2_warning (inode->i_sb, "ext2_bmap", "block < 0");
 134                 return 0;
 135         }
 136         if (block >= EXT2_NDIR_BLOCKS + addr_per_block +
 137                      addr_per_block * addr_per_block +
 138                      addr_per_block * addr_per_block * addr_per_block) {
 139                 ext2_warning (inode->i_sb, "ext2_bmap", "block > big");
 140                 return 0;
 141         }
 142         if (block < EXT2_NDIR_BLOCKS)
 143                 return inode_bmap (inode, block);
 144         block -= EXT2_NDIR_BLOCKS;
 145         if (block < addr_per_block) {
 146                 i = inode_bmap (inode, EXT2_IND_BLOCK);
 147                 if (!i)
 148                         return 0;
 149                 return block_bmap (bread (inode->i_dev, i,
 150                                           inode->i_sb->s_blocksize), block);
 151         }
 152         block -= addr_per_block;
 153         if (block < addr_per_block * addr_per_block) {
 154                 i = inode_bmap (inode, EXT2_DIND_BLOCK);
 155                 if (!i)
 156                         return 0;
 157                 i = block_bmap (bread (inode->i_dev, i,
 158                                        inode->i_sb->s_blocksize),
 159                                 block / addr_per_block);
 160                 if (!i)
 161                         return 0;
 162                 return block_bmap (bread (inode->i_dev, i,
 163                                           inode->i_sb->s_blocksize),
 164                                    block & (addr_per_block - 1));
 165         }
 166         block -= addr_per_block * addr_per_block;
 167         i = inode_bmap (inode, EXT2_TIND_BLOCK);
 168         if (!i)
 169                 return 0;
 170         i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
 171                         block / (addr_per_block * addr_per_block));
 172         if (!i)
 173                 return 0;
 174         i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
 175                         (block / addr_per_block) & (addr_per_block - 1));
 176         if (!i)
 177                 return 0;
 178         return block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize),
 179                            block & (addr_per_block - 1));
 180 }
 181 
 182 static struct buffer_head * inode_getblk (struct inode * inode, int nr,
     /* [previous][next][first][last][top][bottom][index][help] */
 183                                           int create, int new_block, int * err)
 184 {
 185         int tmp, goal = 0;
 186         unsigned long * p;
 187         struct buffer_head * result;
 188         int blocks = inode->i_sb->s_blocksize / 512;
 189 
 190         p = inode->u.ext2_i.i_data + nr;
 191 repeat:
 192         tmp = *p;
 193         if (tmp) {
 194                 result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize);
 195                 if (tmp == *p)
 196                         return result;
 197                 brelse (result);
 198                 goto repeat;
 199         }
 200         if (!create || new_block >= 
 201             (current->rlim[RLIMIT_FSIZE].rlim_cur >>
 202              EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
 203                 *err = -EFBIG;
 204                 return NULL;
 205         }
 206         if (inode->u.ext2_i.i_next_alloc_block == new_block)
 207                 goal = inode->u.ext2_i.i_next_alloc_goal;
 208 
 209         ext2_debug ("hint = %d,", goal);
 210 
 211         if (!goal) {
 212                 for (tmp = nr - 1; tmp >= 0; tmp--) {
 213                         if (inode->u.ext2_i.i_data[tmp]) {
 214                                 goal = inode->u.ext2_i.i_data[tmp];
 215                                 break;
 216                         }
 217                 }
 218                 if (!goal)
 219                         goal = (inode->u.ext2_i.i_block_group * 
 220                                 EXT2_BLOCKS_PER_GROUP(inode->i_sb)) +
 221                                inode->i_sb->u.ext2_sb.s_es->s_first_data_block;
 222         }
 223 
 224         ext2_debug ("goal = %d.\n", goal);
 225 
 226         tmp = ext2_alloc_block (inode, goal);
 227         if (!tmp)
 228                 return NULL;
 229         result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize);
 230         if (*p) {
 231                 ext2_free_blocks (inode->i_sb, tmp, 1);
 232                 brelse (result);
 233                 goto repeat;
 234         }
 235         *p = tmp;
 236         inode->u.ext2_i.i_next_alloc_block = new_block;
 237         inode->u.ext2_i.i_next_alloc_goal = tmp;
 238         inode->i_ctime = CURRENT_TIME;
 239         inode->i_blocks += blocks;
 240         if (IS_SYNC(inode) || inode->u.ext2_i.i_osync)
 241                 ext2_sync_inode (inode);
 242         else
 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,
 249                                           int create, int blocksize, 
 250                                           int new_block, int * err)
 251 {
 252         int tmp, goal = 0;
 253         unsigned long * p;
 254         struct buffer_head * result;
 255         int blocks = inode->i_sb->s_blocksize / 512;
 256 
 257         if (!bh)
 258                 return NULL;
 259         if (!bh->b_uptodate) {
 260                 ll_rw_block (READ, 1, &bh);
 261                 wait_on_buffer (bh);
 262                 if (!bh->b_uptodate) {
 263                         brelse (bh);
 264                         return NULL;
 265                 }
 266         }
 267         p = (unsigned long *) bh->b_data + nr;
 268 repeat:
 269         tmp = *p;
 270         if (tmp) {
 271                 result = getblk (bh->b_dev, tmp, blocksize);
 272                 if (tmp == *p) {
 273                         brelse (bh);
 274                         return result;
 275                 }
 276                 brelse (result);
 277                 goto repeat;
 278         }
 279         if (!create || new_block >= 
 280             (current->rlim[RLIMIT_FSIZE].rlim_cur >> 
 281              EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
 282                 brelse (bh);
 283                 *err = -EFBIG;
 284                 return NULL;
 285         }
 286         if (inode->u.ext2_i.i_next_alloc_block == new_block)
 287                 goal = inode->u.ext2_i.i_next_alloc_goal;
 288         if (!goal) {
 289                 for (tmp = nr - 1; tmp >= 0; tmp--) {
 290                         if (((unsigned long *) bh->b_data)[tmp]) {
 291                                 goal = ((unsigned long *)bh->b_data)[tmp];
 292                                 break;
 293                         }
 294                 }
 295                 if (!goal)
 296                         goal = bh->b_blocknr;
 297         }
 298         tmp = ext2_alloc_block (inode, goal);
 299         if (!tmp) {
 300                 brelse (bh);
 301                 return NULL;
 302         }
 303         result = getblk (bh->b_dev, tmp, blocksize);
 304         if (*p) {
 305                 ext2_free_blocks (inode->i_sb, tmp, 1);
 306                 brelse (result);
 307                 goto repeat;
 308         }
 309         *p = tmp;
 310         mark_buffer_dirty(bh, 1);
 311         if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) {
 312                 ll_rw_block (WRITE, 1, &bh);
 313                 wait_on_buffer (bh);
 314         }
 315         inode->i_ctime = CURRENT_TIME;
 316         inode->i_blocks += blocks;
 317         inode->i_dirt = 1;
 318         inode->u.ext2_i.i_next_alloc_block = new_block;
 319         inode->u.ext2_i.i_next_alloc_goal = tmp;
 320         brelse (bh);
 321         return result;
 322 }
 323 
 324 static int block_getcluster (struct inode * inode, struct buffer_head * bh,
     /* [previous][next][first][last][top][bottom][index][help] */
 325                                           int nr,
 326                                           int blocksize)
 327 {
 328         unsigned long * p;
 329         int firstblock = 0;
 330         int result = 0;
 331         int i;
 332 
 333         /* Check to see if clustering possible here. */
 334 
 335         if(!bh) return 0;
 336 
 337         if(nr % (PAGE_SIZE / inode->i_sb->s_blocksize) != 0) goto out;
 338         if(nr + 3 > EXT2_ADDR_PER_BLOCK(inode->i_sb)) goto out;
 339 
 340         for(i=0; i< (PAGE_SIZE / inode->i_sb->s_blocksize); i++) {
 341           p = (unsigned long *) bh->b_data + nr + i;
 342           
 343           /* All blocks in cluster must already be allocated */
 344           if(*p == 0) goto out;
 345           
 346           /* See if aligned correctly */
 347           if(i==0) firstblock = *p;
 348           else if(*p != firstblock + i) goto out;
 349         };
 350         
 351         p = (unsigned long *) bh->b_data + nr;
 352         result = generate_cluster(bh->b_dev, (int *) p, blocksize);
 353 
 354       out:
 355         brelse(bh);
 356         return result;
 357 }
 358 
 359 struct buffer_head * ext2_getblk (struct inode * inode, long block,
     /* [previous][next][first][last][top][bottom][index][help] */
 360                                   int create, int * err)
 361 {
 362         struct buffer_head * bh;
 363         unsigned long b;
 364         unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 365 
 366         *err = -EIO;
 367         if (block < 0) {
 368                 ext2_warning (inode->i_sb, "ext2_getblk", "block < 0");
 369                 return NULL;
 370         }
 371         if (block > EXT2_NDIR_BLOCKS + addr_per_block  +
 372                     addr_per_block * addr_per_block +
 373                     addr_per_block * addr_per_block * addr_per_block) {
 374                 ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
 375                 return NULL;
 376         }
 377         /*
 378          * If this is a sequential block allocation, set the next_alloc_block
 379          * to this block now so that all the indblock and data block
 380          * allocations use the same goal zone
 381          */
 382 
 383         ext2_debug ("block %lu, next %lu, goal %lu.\n", block, 
 384                     inode->u.ext2_i.i_next_alloc_block,
 385                     inode->u.ext2_i.i_next_alloc_goal);
 386 
 387         if (block == inode->u.ext2_i.i_next_alloc_block + 1) {
 388                 inode->u.ext2_i.i_next_alloc_block++;
 389                 inode->u.ext2_i.i_next_alloc_goal++;
 390         }
 391 
 392         *err = -ENOSPC;
 393         b = block;
 394         if (block < EXT2_NDIR_BLOCKS)
 395                 return inode_getblk (inode, block, create, b, err);
 396         block -= EXT2_NDIR_BLOCKS;
 397         if (block < addr_per_block) {
 398                 bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, err);
 399                 return block_getblk (inode, bh, block, create,
 400                                      inode->i_sb->s_blocksize, b, err);
 401         }
 402         block -= addr_per_block;
 403         if (block < addr_per_block * addr_per_block) {
 404                 bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, err);
 405                 bh = block_getblk (inode, bh, block / addr_per_block, create,
 406                                    inode->i_sb->s_blocksize, b, err);
 407                 return block_getblk (inode, bh, block & (addr_per_block - 1),
 408                                      create, inode->i_sb->s_blocksize, b, err);
 409         }
 410         block -= addr_per_block * addr_per_block;
 411         bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, err);
 412         bh = block_getblk (inode, bh, block/(addr_per_block * addr_per_block),
 413                            create, inode->i_sb->s_blocksize, b, err);
 414         bh = block_getblk (inode, bh, (block/addr_per_block) & (addr_per_block - 1),
 415                            create, inode->i_sb->s_blocksize, b, err);
 416         return block_getblk (inode, bh, block & (addr_per_block - 1), create,
 417                              inode->i_sb->s_blocksize, b, err);
 418 }
 419 
 420 int ext2_getcluster (struct inode * inode, long block)
     /* [previous][next][first][last][top][bottom][index][help] */
 421 {
 422         struct buffer_head * bh;
 423         int err, create;
 424         unsigned long b;
 425         unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 426 
 427         create = 0;
 428         err = -EIO;
 429         if (block < 0) {
 430                 ext2_warning (inode->i_sb, "ext2_getblk", "block < 0");
 431                 return 0;
 432         }
 433         if (block > EXT2_NDIR_BLOCKS + addr_per_block  +
 434                     addr_per_block * addr_per_block +
 435                     addr_per_block * addr_per_block * addr_per_block) {
 436                 ext2_warning (inode->i_sb, "ext2_getblk", "block > big");
 437                 return 0;
 438         }
 439 
 440         err = -ENOSPC;
 441         b = block;
 442         if (block < EXT2_NDIR_BLOCKS) return 0;
 443 
 444         block -= EXT2_NDIR_BLOCKS;
 445 
 446         if (block < addr_per_block) {
 447                 bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, &err);
 448                 return block_getcluster (inode, bh, block, 
 449                                          inode->i_sb->s_blocksize);
 450         }
 451         block -= addr_per_block;
 452         if (block < addr_per_block * addr_per_block) {
 453                 bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, &err);
 454                 bh = block_getblk (inode, bh, block / addr_per_block, create,
 455                                    inode->i_sb->s_blocksize, b, &err);
 456                 return block_getcluster (inode, bh, block & (addr_per_block - 1),
 457                                      inode->i_sb->s_blocksize);
 458         }
 459         block -= addr_per_block * addr_per_block;
 460         bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, &err);
 461         bh = block_getblk (inode, bh, block/(addr_per_block * addr_per_block),
 462                            create, inode->i_sb->s_blocksize, b, &err);
 463         bh = block_getblk (inode, bh, (block/addr_per_block) & (addr_per_block - 1),
 464                            create, inode->i_sb->s_blocksize, b, &err);
 465         return block_getcluster (inode, bh, block & (addr_per_block - 1),
 466                                  inode->i_sb->s_blocksize);
 467 }
 468 
 469 struct buffer_head * ext2_bread (struct inode * inode, int block, 
     /* [previous][next][first][last][top][bottom][index][help] */
 470                                  int create, int *err)
 471 {
 472         struct buffer_head * bh;
 473 
 474         bh = ext2_getblk (inode, block, create, err);
 475         if (!bh || bh->b_uptodate)
 476                 return bh;
 477         ll_rw_block (READ, 1, &bh);
 478         wait_on_buffer (bh);
 479         if (bh->b_uptodate)
 480                 return bh;
 481         brelse (bh);
 482         *err = -EIO;
 483         return NULL;
 484 }
 485 
 486 void ext2_read_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 487 {
 488         struct buffer_head * bh;
 489         struct ext2_inode * raw_inode;
 490         unsigned long block_group;
 491         unsigned long group_desc;
 492         unsigned long desc;
 493         unsigned long block;
 494         struct ext2_group_desc * gdp;
 495 
 496         if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
 497              inode->i_ino != EXT2_ACL_DATA_INO && inode->i_ino < EXT2_FIRST_INO) ||
 498             inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
 499                 ext2_error (inode->i_sb, "ext2_read_inode",
 500                             "bad inode number: %lu", inode->i_ino);
 501                 return;
 502         }
 503         block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
 504         if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
 505                 ext2_panic (inode->i_sb, "ext2_read_inode",
 506                             "group >= groups count");
 507         group_desc = block_group / EXT2_DESC_PER_BLOCK(inode->i_sb);
 508         desc = block_group % EXT2_DESC_PER_BLOCK(inode->i_sb);
 509         bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
 510         if (!bh)
 511                 ext2_panic (inode->i_sb, "ext2_read_inode",
 512                             "Descriptor not loaded");
 513         gdp = (struct ext2_group_desc *) bh->b_data;
 514         block = gdp[desc].bg_inode_table +
 515                 (((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb))
 516                  / EXT2_INODES_PER_BLOCK(inode->i_sb));
 517         if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
 518                 ext2_panic (inode->i_sb, "ext2_read_inode",
 519                             "unable to read i-node block - "
 520                             "inode=%lu, block=%lu", inode->i_ino, block);
 521         raw_inode = ((struct ext2_inode *) bh->b_data) +
 522                 (inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
 523         inode->i_mode = raw_inode->i_mode;
 524         inode->i_uid = raw_inode->i_uid;
 525         inode->i_gid = raw_inode->i_gid;
 526         inode->i_nlink = raw_inode->i_links_count;
 527         inode->i_size = raw_inode->i_size;
 528         inode->i_atime = raw_inode->i_atime;
 529         inode->i_ctime = raw_inode->i_ctime;
 530         inode->i_mtime = raw_inode->i_mtime;
 531         inode->u.ext2_i.i_dtime = raw_inode->i_dtime;
 532         inode->i_blksize = inode->i_sb->s_blocksize;
 533         inode->i_blocks = raw_inode->i_blocks;
 534         inode->i_version = ++event;
 535         inode->u.ext2_i.i_flags = raw_inode->i_flags;
 536         inode->u.ext2_i.i_faddr = raw_inode->i_faddr;
 537         inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
 538         inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
 539         inode->u.ext2_i.i_osync = 0;
 540         inode->u.ext2_i.i_file_acl = raw_inode->i_file_acl;
 541         inode->u.ext2_i.i_dir_acl = raw_inode->i_dir_acl;
 542         inode->u.ext2_i.i_version = raw_inode->i_version;
 543         inode->u.ext2_i.i_block_group = block_group;
 544         inode->u.ext2_i.i_next_alloc_block = 0;
 545         inode->u.ext2_i.i_next_alloc_goal = 0;
 546         if (inode->u.ext2_i.i_prealloc_count)
 547                 ext2_error (inode->i_sb, "ext2_read_inode",
 548                             "New inode has non-zero prealloc count!");
 549         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 550                 inode->i_rdev = raw_inode->i_block[0];
 551         else for (block = 0; block < EXT2_N_BLOCKS; block++)
 552                 inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
 553         brelse (bh);
 554         inode->i_op = NULL;
 555         if (inode->i_ino == EXT2_ACL_IDX_INO ||
 556             inode->i_ino == EXT2_ACL_DATA_INO)
 557                 /* Nothing to do */ ;
 558         else if (S_ISREG(inode->i_mode))
 559                 inode->i_op = &ext2_file_inode_operations;
 560         else if (S_ISDIR(inode->i_mode))
 561                 inode->i_op = &ext2_dir_inode_operations;
 562         else if (S_ISLNK(inode->i_mode))
 563                 inode->i_op = &ext2_symlink_inode_operations;
 564         else if (S_ISCHR(inode->i_mode))
 565                 inode->i_op = &chrdev_inode_operations;
 566         else if (S_ISBLK(inode->i_mode))
 567                 inode->i_op = &blkdev_inode_operations;
 568         else if (S_ISFIFO(inode->i_mode))
 569                 init_fifo(inode);
 570         if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
 571                 inode->i_flags |= MS_SYNCHRONOUS;
 572         if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL)
 573                 inode->i_flags |= S_APPEND;
 574         if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)
 575                 inode->i_flags |= S_IMMUTABLE;
 576 }
 577 
 578 static struct buffer_head * ext2_update_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 579 {
 580         struct buffer_head * bh;
 581         struct ext2_inode * raw_inode;
 582         unsigned long block_group;
 583         unsigned long group_desc;
 584         unsigned long desc;
 585         unsigned long block;
 586         struct ext2_group_desc * gdp;
 587 
 588         if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino < EXT2_FIRST_INO) ||
 589             inode->i_ino > inode->i_sb->u.ext2_sb.s_es->s_inodes_count) {
 590                 ext2_error (inode->i_sb, "ext2_write_inode",
 591                             "bad inode number: %lu", inode->i_ino);
 592                 return 0;
 593         }
 594         block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
 595         if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count)
 596                 ext2_panic (inode->i_sb, "ext2_write_inode",
 597                             "group >= groups count");
 598         group_desc = block_group / EXT2_DESC_PER_BLOCK(inode->i_sb);
 599         desc = block_group % EXT2_DESC_PER_BLOCK(inode->i_sb);
 600         bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
 601         if (!bh)
 602                 ext2_panic (inode->i_sb, "ext2_write_inode",
 603                             "Descriptor not loaded");
 604         gdp = (struct ext2_group_desc *) bh->b_data;
 605         block = gdp[desc].bg_inode_table +
 606                 (((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb))
 607                  / EXT2_INODES_PER_BLOCK(inode->i_sb));
 608         if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize)))
 609                 ext2_panic (inode->i_sb, "ext2_write_inode",
 610                             "unable to read i-node block - "
 611                             "inode=%lu, block=%lu", inode->i_ino, block);
 612         raw_inode = ((struct ext2_inode *)bh->b_data) +
 613                 (inode->i_ino - 1) % EXT2_INODES_PER_BLOCK(inode->i_sb);
 614         raw_inode->i_mode = inode->i_mode;
 615         raw_inode->i_uid = inode->i_uid;
 616         raw_inode->i_gid = inode->i_gid;
 617         raw_inode->i_links_count = inode->i_nlink;
 618         raw_inode->i_size = inode->i_size;
 619         raw_inode->i_atime = inode->i_atime;
 620         raw_inode->i_ctime = inode->i_ctime;
 621         raw_inode->i_mtime = inode->i_mtime;
 622         raw_inode->i_blocks = inode->i_blocks;
 623         raw_inode->i_dtime = inode->u.ext2_i.i_dtime;
 624         raw_inode->i_flags = inode->u.ext2_i.i_flags;
 625         raw_inode->i_faddr = inode->u.ext2_i.i_faddr;
 626         raw_inode->i_frag = inode->u.ext2_i.i_frag_no;
 627         raw_inode->i_fsize = inode->u.ext2_i.i_frag_size;
 628         raw_inode->i_file_acl = inode->u.ext2_i.i_file_acl;
 629         raw_inode->i_dir_acl = inode->u.ext2_i.i_dir_acl;
 630         raw_inode->i_version = inode->u.ext2_i.i_version;
 631         if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 632                 raw_inode->i_block[0] = inode->i_rdev;
 633         else for (block = 0; block < EXT2_N_BLOCKS; block++)
 634                 raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
 635         mark_buffer_dirty(bh, 1);
 636         inode->i_dirt = 0;
 637         return bh;
 638 }
 639 
 640 void ext2_write_inode (struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 641 {
 642         struct buffer_head * bh;
 643         bh = ext2_update_inode (inode);
 644         brelse (bh);
 645 }
 646 
 647 int ext2_sync_inode (struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 648 {
 649         int err = 0;
 650         struct buffer_head *bh;
 651 
 652         bh = ext2_update_inode (inode);
 653         if (bh && bh->b_dirt)
 654         {
 655                 ll_rw_block (WRITE, 1, &bh);
 656                 wait_on_buffer (bh);
 657                 if (bh->b_req && !bh->b_uptodate)
 658                 {
 659                         printk ("IO error syncing ext2 inode [%04x:%08lx]\n",
 660                                 inode->i_dev, inode->i_ino);
 661                         err = -1;
 662                 }
 663         }
 664         else if (!bh)
 665                 err = -1;
 666         brelse (bh);
 667         return err;
 668 }

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