page-allocator: add inactive ratio calculation function of each zone
[sfrench/cifs-2.6.git] / fs / ext2 / inode.c
index b43b9556366324271165f46a996fc965fe9b5a17..29ed682061f6453341c48a0c0f5aab34ac42cd89 100644 (file)
@@ -41,8 +41,6 @@ MODULE_AUTHOR("Remy Card and others");
 MODULE_DESCRIPTION("Second Extended Filesystem");
 MODULE_LICENSE("GPL");
 
-static int ext2_update_inode(struct inode * inode, int do_sync);
-
 /*
  * Test whether an inode is a fast symlink.
  */
@@ -66,7 +64,7 @@ void ext2_delete_inode (struct inode * inode)
                goto no_delete;
        EXT2_I(inode)->i_dtime  = get_seconds();
        mark_inode_dirty(inode);
-       ext2_update_inode(inode, inode_needs_sync(inode));
+       ext2_write_inode(inode, inode_needs_sync(inode));
 
        inode->i_size = 0;
        if (inode->i_blocks)
@@ -590,9 +588,8 @@ static int ext2_get_blocks(struct inode *inode,
 
        if (depth == 0)
                return (err);
-reread:
-       partial = ext2_get_branch(inode, depth, offsets, chain, &err);
 
+       partial = ext2_get_branch(inode, depth, offsets, chain, &err);
        /* Simplest case - block found, no allocation needed */
        if (!partial) {
                first_block = le32_to_cpu(chain[depth - 1].key);
@@ -602,15 +599,16 @@ reread:
                while (count < maxblocks && count <= blocks_to_boundary) {
                        ext2_fsblk_t blk;
 
-                       if (!verify_chain(chain, partial)) {
+                       if (!verify_chain(chain, chain + depth - 1)) {
                                /*
                                 * Indirect block might be removed by
                                 * truncate while we were reading it.
                                 * Handling of that case: forget what we've
                                 * got now, go to reread.
                                 */
+                               err = -EAGAIN;
                                count = 0;
-                               goto changed;
+                               break;
                        }
                        blk = le32_to_cpu(*(chain[depth-1].p + count));
                        if (blk == first_block + count)
@@ -618,7 +616,8 @@ reread:
                        else
                                break;
                }
-               goto got_it;
+               if (err != -EAGAIN)
+                       goto got_it;
        }
 
        /* Next simple case - plain lookup or failed read of indirect block */
@@ -626,6 +625,33 @@ reread:
                goto cleanup;
 
        mutex_lock(&ei->truncate_mutex);
+       /*
+        * If the indirect block is missing while we are reading
+        * the chain(ext3_get_branch() returns -EAGAIN err), or
+        * if the chain has been changed after we grab the semaphore,
+        * (either because another process truncated this branch, or
+        * another get_block allocated this branch) re-grab the chain to see if
+        * the request block has been allocated or not.
+        *
+        * Since we already block the truncate/other get_block
+        * at this point, we will have the current copy of the chain when we
+        * splice the branch into the tree.
+        */
+       if (err == -EAGAIN || !verify_chain(chain, partial)) {
+               while (partial > chain) {
+                       brelse(partial->bh);
+                       partial--;
+               }
+               partial = ext2_get_branch(inode, depth, offsets, chain, &err);
+               if (!partial) {
+                       count++;
+                       mutex_unlock(&ei->truncate_mutex);
+                       if (err)
+                               goto cleanup;
+                       clear_buffer_new(bh_result);
+                       goto got_it;
+               }
+       }
 
        /*
         * Okay, we need to do block allocation.  Lazily initialize the block
@@ -683,12 +709,6 @@ cleanup:
                partial--;
        }
        return err;
-changed:
-       while (partial > chain) {
-               brelse(partial->bh);
-               partial--;
-       }
-       goto reread;
 }
 
 int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
@@ -1315,7 +1335,7 @@ bad_inode:
        return ERR_PTR(ret);
 }
 
-static int ext2_update_inode(struct inode * inode, int do_sync)
+int ext2_write_inode(struct inode *inode, int do_sync)
 {
        struct ext2_inode_info *ei = EXT2_I(inode);
        struct super_block *sb = inode->i_sb;
@@ -1420,11 +1440,6 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
        return err;
 }
 
-int ext2_write_inode(struct inode *inode, int wait)
-{
-       return ext2_update_inode(inode, wait);
-}
-
 int ext2_sync_inode(struct inode *inode)
 {
        struct writeback_control wbc = {