]> err.no Git - linux-2.6/blobdiff - fs/ext4/inode.c
[PATCH] nfsd: change uses of f_{dentry, vfsmnt} to use f_path
[linux-2.6] / fs / ext4 / inode.c
index 7275d60dcc598307872491aeb73b6b57a2a8616f..a127cc03c9fa2868739ded1b98c7cd6d0d7ecc8b 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/time.h>
-#include <linux/ext4_jbd.h>
-#include <linux/jbd.h>
+#include <linux/ext4_jbd2.h>
+#include <linux/jbd2.h>
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
@@ -40,8 +40,6 @@
 #include "xattr.h"
 #include "acl.h"
 
-static int ext4_writepage_trans_blocks(struct inode *inode);
-
 /*
  * Test whether an inode is a fast symlink.
  */
@@ -84,7 +82,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
        if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
            (!is_metadata && !ext4_should_journal_data(inode))) {
                if (bh) {
-                       BUFFER_TRACE(bh, "call journal_forget");
+                       BUFFER_TRACE(bh, "call jbd2_journal_forget");
                        return ext4_journal_forget(handle, bh);
                }
                return 0;
@@ -657,7 +655,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
 failed:
        /* Allocation failed, free what we already allocated */
        for (i = 1; i <= n ; i++) {
-               BUFFER_TRACE(branch[i].bh, "call journal_forget");
+               BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
                ext4_journal_forget(handle, branch[i].bh);
        }
        for (i = 0; i <indirect_blks; i++)
@@ -758,7 +756,7 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
 
 err_out:
        for (i = 1; i <= num; i++) {
-               BUFFER_TRACE(where[i].bh, "call journal_forget");
+               BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
                ext4_journal_forget(handle, where[i].bh);
                ext4_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
        }
@@ -804,6 +802,7 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
        ext4_fsblk_t first_block = 0;
 
 
+       J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
        J_ASSERT(handle != NULL || create == 0);
        depth = ext4_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
 
@@ -984,7 +983,7 @@ static int ext4_get_block(struct inode *inode, sector_t iblock,
 
 get_block:
        if (ret == 0) {
-               ret = ext4_get_blocks_handle(handle, inode, iblock,
+               ret = ext4_get_blocks_wrap(handle, inode, iblock,
                                        max_blocks, bh_result, create, 0);
                if (ret > 0) {
                        bh_result->b_size = (ret << inode->i_blkbits);
@@ -1008,7 +1007,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
        dummy.b_state = 0;
        dummy.b_blocknr = -1000;
        buffer_trace_init(&dummy.b_history);
-       err = ext4_get_blocks_handle(handle, inode, block, 1,
+       err = ext4_get_blocks_wrap(handle, inode, block, 1,
                                        &dummy, create, 1);
        /*
         * ext4_get_blocks_handle() returns number of blocks
@@ -1119,7 +1118,7 @@ static int walk_page_buffers(     handle_t *handle,
  * To preserve ordering, it is essential that the hole instantiation and
  * the data write be encapsulated in a single transaction.  We cannot
  * close off a transaction and start a new one between the ext4_get_block()
- * and the commit_write().  So doing the journal_start at the start of
+ * and the commit_write().  So doing the jbd2_journal_start at the start of
  * prepare_write() is the right place.
  *
  * Also, this function can nest inside ext4_writepage() ->
@@ -1135,7 +1134,7 @@ static int walk_page_buffers(     handle_t *handle,
  * transaction open and was blocking on the quota lock - a ranking
  * violation.
  *
- * So what we do is to rely on the fact that journal_stop/journal_start
+ * So what we do is to rely on the fact that jbd2_journal_stop/journal_start
  * will _not_ run commit under these circumstances because handle->h_ref
  * is elevated.  We'll still have enough credits for the tiny quotafile
  * write.
@@ -1148,43 +1147,108 @@ static int do_journal_get_write_access(handle_t *handle,
        return ext4_journal_get_write_access(handle, bh);
 }
 
+/*
+ * The idea of this helper function is following:
+ * if prepare_write has allocated some blocks, but not all of them, the
+ * transaction must include the content of the newly allocated blocks.
+ * This content is expected to be set to zeroes by block_prepare_write().
+ * 2006/10/14  SAW
+ */
+static int ext4_prepare_failure(struct file *file, struct page *page,
+                               unsigned from, unsigned to)
+{
+       struct address_space *mapping;
+       struct buffer_head *bh, *head, *next;
+       unsigned block_start, block_end;
+       unsigned blocksize;
+       int ret;
+       handle_t *handle = ext4_journal_current_handle();
+
+       mapping = page->mapping;
+       if (ext4_should_writeback_data(mapping->host)) {
+               /* optimization: no constraints about data */
+skip:
+               return ext4_journal_stop(handle);
+       }
+
+       head = page_buffers(page);
+       blocksize = head->b_size;
+       for (   bh = head, block_start = 0;
+               bh != head || !block_start;
+               block_start = block_end, bh = next)
+       {
+               next = bh->b_this_page;
+               block_end = block_start + blocksize;
+               if (block_end <= from)
+                       continue;
+               if (block_start >= to) {
+                       block_start = to;
+                       break;
+               }
+               if (!buffer_mapped(bh))
+               /* prepare_write failed on this bh */
+                       break;
+               if (ext4_should_journal_data(mapping->host)) {
+                       ret = do_journal_get_write_access(handle, bh);
+                       if (ret) {
+                               ext4_journal_stop(handle);
+                               return ret;
+                       }
+               }
+       /*
+        * block_start here becomes the first block where the current iteration
+        * of prepare_write failed.
+        */
+       }
+       if (block_start <= from)
+               goto skip;
+
+       /* commit allocated and zeroed buffers */
+       return mapping->a_ops->commit_write(file, page, from, block_start);
+}
+
 static int ext4_prepare_write(struct file *file, struct page *page,
                              unsigned from, unsigned to)
 {
        struct inode *inode = page->mapping->host;
-       int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
+       int ret, ret2;
+       int needed_blocks = ext4_writepage_trans_blocks(inode);
        handle_t *handle;
        int retries = 0;
 
 retry:
        handle = ext4_journal_start(inode, needed_blocks);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               goto out;
-       }
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
        if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
                ret = nobh_prepare_write(page, from, to, ext4_get_block);
        else
                ret = block_prepare_write(page, from, to, ext4_get_block);
        if (ret)
-               goto prepare_write_failed;
+               goto failure;
 
        if (ext4_should_journal_data(inode)) {
                ret = walk_page_buffers(handle, page_buffers(page),
                                from, to, NULL, do_journal_get_write_access);
+               if (ret)
+                       /* fatal error, just put the handle and return */
+                       ext4_journal_stop(handle);
        }
-prepare_write_failed:
-       if (ret)
-               ext4_journal_stop(handle);
+       return ret;
+
+failure:
+       ret2 = ext4_prepare_failure(file, page, from, to);
+       if (ret2 < 0)
+               return ret2;
        if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
-out:
+       /* retry number exceeded, or other error like -EDQUOT */
        return ret;
 }
 
 int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 {
-       int err = journal_dirty_data(handle, bh);
+       int err = jbd2_journal_dirty_data(handle, bh);
        if (err)
                ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
                                                bh, handle,err);
@@ -1333,9 +1397,9 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
 
                EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
                journal = EXT4_JOURNAL(inode);
-               journal_lock_updates(journal);
-               err = journal_flush(journal);
-               journal_unlock_updates(journal);
+               jbd2_journal_lock_updates(journal);
+               err = jbd2_journal_flush(journal);
+               jbd2_journal_unlock_updates(journal);
 
                if (err)
                        return 0;
@@ -1356,7 +1420,7 @@ static int bput_one(handle_t *handle, struct buffer_head *bh)
        return 0;
 }
 
-static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
+static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
 {
        if (buffer_mapped(bh))
                return ext4_journal_dirty_data(handle, bh);
@@ -1464,7 +1528,7 @@ static int ext4_ordered_writepage(struct page *page,
         */
        if (ret == 0) {
                err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE,
-                                       NULL, journal_dirty_data_fn);
+                                       NULL, jbd2_journal_dirty_data_fn);
                if (!ret)
                        ret = err;
        }
@@ -1595,7 +1659,7 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset)
        if (offset == 0)
                ClearPageChecked(page);
 
-       journal_invalidatepage(journal, page, offset);
+       jbd2_journal_invalidatepage(journal, page, offset);
 }
 
 static int ext4_releasepage(struct page *page, gfp_t wait)
@@ -1605,7 +1669,7 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
        WARN_ON(PageChecked(page));
        if (!page_has_buffers(page))
                return 0;
-       return journal_try_to_free_buffers(journal, page, wait);
+       return jbd2_journal_try_to_free_buffers(journal, page, wait);
 }
 
 /*
@@ -1759,7 +1823,7 @@ void ext4_set_aops(struct inode *inode)
  * This required during truncate. We need to physically zero the tail end
  * of that block so it doesn't yield old data if the file is later grown.
  */
-static int ext4_block_truncate_page(handle_t *handle, struct page *page,
+int ext4_block_truncate_page(handle_t *handle, struct page *page,
                struct address_space *mapping, loff_t from)
 {
        ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT;
@@ -1982,11 +2046,11 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
 
        /*
         * Any buffers which are on the journal will be in memory. We find
-        * them on the hash table so journal_revoke() will run journal_forget()
+        * them on the hash table so jbd2_journal_revoke() will run jbd2_journal_forget()
         * on them.  We've already detached each block from the file, so
-        * bforget() in journal_forget() should be safe.
+        * bforget() in jbd2_journal_forget() should be safe.
         *
-        * AKPM: turn on bforget in journal_forget()!!!
+        * AKPM: turn on bforget in jbd2_journal_forget()!!!
         */
        for (p = first; p < last; p++) {
                u32 nr = le32_to_cpu(*p);
@@ -2116,7 +2180,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
                         */
                        if (!bh) {
                                ext4_error(inode->i_sb, "ext4_free_branches",
-                                          "Read failure, inode=%lu, block="E3FSBLK,
+                                          "Read failure, inode=%lu, block=%llu",
                                           inode->i_ino, nr);
                                continue;
                        }
@@ -2132,11 +2196,11 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
                         * We've probably journalled the indirect block several
                         * times during the truncate.  But it's no longer
                         * needed and we now drop it from the transaction via
-                        * journal_revoke().
+                        * jbd2_journal_revoke().
                         *
                         * That's easy if it's exclusively part of this
                         * transaction.  But if it's part of the committing
-                        * transaction then journal_forget() will simply
+                        * transaction then jbd2_journal_forget() will simply
                         * brelse() it.  That means that if the underlying
                         * block is reallocated in ext4_get_block(),
                         * unmap_underlying_metadata() will find this block
@@ -2251,7 +2315,7 @@ void ext4_truncate(struct inode *inode)
 
        /*
         * We have to lock the EOF page here, because lock_page() nests
-        * outside journal_start().
+        * outside jbd2_journal_start().
         */
        if ((inode->i_size & (blocksize - 1)) == 0) {
                /* Block boundary? Nothing to do */
@@ -2263,6 +2327,9 @@ void ext4_truncate(struct inode *inode)
                        return;
        }
 
+       if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+               return ext4_ext_truncate(inode, page);
+
        handle = start_transaction(inode);
        if (IS_ERR(handle)) {
                if (page) {
@@ -2430,13 +2497,14 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
                return 0;
        }
 
-       gdp = (struct ext4_group_desc *)bh->b_data;
+       gdp = (struct ext4_group_desc *)((__u8 *)bh->b_data +
+               desc * EXT4_DESC_SIZE(sb));
        /*
         * Figure out the offset within the block group inode table
         */
        offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
                EXT4_INODE_SIZE(sb);
-       block = le32_to_cpu(gdp[desc].bg_inode_table) +
+       block = ext4_inode_table(sb, gdp) +
                (offset >> EXT4_BLOCK_SIZE_BITS(sb));
 
        iloc->block_group = block_group;
@@ -2464,7 +2532,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
        if (!bh) {
                ext4_error (inode->i_sb, "ext4_get_inode_loc",
                                "unable to read inode block - "
-                               "inode=%lu, block="E3FSBLK,
+                               "inode=%lu, block=%llu",
                                 inode->i_ino, block);
                return -EIO;
        }
@@ -2504,7 +2572,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
                                goto make_io;
 
                        bitmap_bh = sb_getblk(inode->i_sb,
-                                       le32_to_cpu(desc->bg_inode_bitmap));
+                               ext4_inode_bitmap(inode->i_sb, desc));
                        if (!bitmap_bh)
                                goto make_io;
 
@@ -2546,7 +2614,7 @@ make_io:
                if (!buffer_uptodate(bh)) {
                        ext4_error(inode->i_sb, "ext4_get_inode_loc",
                                        "unable to read inode block - "
-                                       "inode=%lu, block="E3FSBLK,
+                                       "inode=%lu, block=%llu",
                                        inode->i_ino, block);
                        brelse(bh);
                        return -EIO;
@@ -2641,6 +2709,10 @@ void ext4_read_inode(struct inode * inode)
        ei->i_frag_size = raw_inode->i_fsize;
 #endif
        ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+       if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+           cpu_to_le32(EXT4_OS_HURD))
+               ei->i_file_acl |=
+                       ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
        if (!S_ISREG(inode->i_mode)) {
                ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
        } else {
@@ -2774,6 +2846,10 @@ static int ext4_do_update_inode(handle_t *handle,
        raw_inode->i_frag = ei->i_frag_no;
        raw_inode->i_fsize = ei->i_frag_size;
 #endif
+       if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+           cpu_to_le32(EXT4_OS_HURD))
+               raw_inode->i_file_acl_high =
+                       cpu_to_le16(ei->i_file_acl >> 32);
        raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
        if (!S_ISREG(inode->i_mode)) {
                raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
@@ -3003,12 +3079,15 @@ err_out:
  * block and work out the exact number of indirects which are touched.  Pah.
  */
 
-static int ext4_writepage_trans_blocks(struct inode *inode)
+int ext4_writepage_trans_blocks(struct inode *inode)
 {
        int bpp = ext4_journal_blocks_per_page(inode);
        int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3;
        int ret;
 
+       if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+               return ext4_ext_writepage_trans_blocks(inode, bpp);
+
        if (ext4_should_journal_data(inode))
                ret = 3 * (bpp + indirects) + 2;
        else
@@ -3035,7 +3114,7 @@ int ext4_mark_iloc_dirty(handle_t *handle,
        /* the do_update_inode consumes one bh->b_count */
        get_bh(iloc->bh);
 
-       /* ext4_do_update_inode() does journal_dirty_metadata */
+       /* ext4_do_update_inode() does jbd2_journal_dirty_metadata */
        err = ext4_do_update_inode(handle, inode, iloc);
        put_bh(iloc->bh);
        return err;
@@ -3153,7 +3232,7 @@ static int ext4_pin_inode(handle_t *handle, struct inode *inode)
                err = ext4_get_inode_loc(inode, &iloc);
                if (!err) {
                        BUFFER_TRACE(iloc.bh, "get_write_access");
-                       err = journal_get_write_access(handle, iloc.bh);
+                       err = jbd2_journal_get_write_access(handle, iloc.bh);
                        if (!err)
                                err = ext4_journal_dirty_metadata(handle,
                                                                  iloc.bh);
@@ -3185,8 +3264,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        if (is_journal_aborted(journal) || IS_RDONLY(inode))
                return -EROFS;
 
-       journal_lock_updates(journal);
-       journal_flush(journal);
+       jbd2_journal_lock_updates(journal);
+       jbd2_journal_flush(journal);
 
        /*
         * OK, there are no updates running now, and all cached data is
@@ -3202,7 +3281,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                EXT4_I(inode)->i_flags &= ~EXT4_JOURNAL_DATA_FL;
        ext4_set_aops(inode);
 
-       journal_unlock_updates(journal);
+       jbd2_journal_unlock_updates(journal);
 
        /* Finally we can mark the inode as dirty. */