Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-2.6-microblaze.git] / fs / ext4 / inode.c
index 325c038..d18852d 100644 (file)
@@ -139,7 +139,6 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
 static void ext4_invalidatepage(struct page *page, unsigned int offset,
                                unsigned int length);
 static int __ext4_journalled_writepage(struct page *page, unsigned int len);
-static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
 static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
                                  int pextents);
 
@@ -869,7 +868,8 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
                 */
                lock_buffer(bh);
                BUFFER_TRACE(bh, "call get_create_access");
-               err = ext4_journal_get_create_access(handle, bh);
+               err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
+                                                    EXT4_JTR_NONE);
                if (unlikely(err)) {
                        unlock_buffer(bh);
                        goto errout;
@@ -954,12 +954,12 @@ out_brelse:
        return err;
 }
 
-int ext4_walk_page_buffers(handle_t *handle,
+int ext4_walk_page_buffers(handle_t *handle, struct inode *inode,
                           struct buffer_head *head,
                           unsigned from,
                           unsigned to,
                           int *partial,
-                          int (*fn)(handle_t *handle,
+                          int (*fn)(handle_t *handle, struct inode *inode,
                                     struct buffer_head *bh))
 {
        struct buffer_head *bh;
@@ -978,7 +978,7 @@ int ext4_walk_page_buffers(handle_t *handle,
                                *partial = 1;
                        continue;
                }
-               err = (*fn)(handle, bh);
+               err = (*fn)(handle, inode, bh);
                if (!ret)
                        ret = err;
        }
@@ -1009,7 +1009,7 @@ int ext4_walk_page_buffers(handle_t *handle,
  * is elevated.  We'll still have enough credits for the tiny quotafile
  * write.
  */
-int do_journal_get_write_access(handle_t *handle,
+int do_journal_get_write_access(handle_t *handle, struct inode *inode,
                                struct buffer_head *bh)
 {
        int dirty = buffer_dirty(bh);
@@ -1028,7 +1028,8 @@ int do_journal_get_write_access(handle_t *handle,
        if (dirty)
                clear_buffer_dirty(bh);
        BUFFER_TRACE(bh, "get write access");
-       ret = ext4_journal_get_write_access(handle, bh);
+       ret = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+                                           EXT4_JTR_NONE);
        if (!ret && dirty)
                ret = ext4_handle_dirty_metadata(handle, NULL, bh);
        return ret;
@@ -1208,8 +1209,8 @@ retry_journal:
                ret = __block_write_begin(page, pos, len, ext4_get_block);
 #endif
        if (!ret && ext4_should_journal_data(inode)) {
-               ret = ext4_walk_page_buffers(handle, page_buffers(page),
-                                            from, to, NULL,
+               ret = ext4_walk_page_buffers(handle, inode,
+                                            page_buffers(page), from, to, NULL,
                                             do_journal_get_write_access);
        }
 
@@ -1253,7 +1254,8 @@ retry_journal:
 }
 
 /* For write_end() in data=journal mode */
-static int write_end_fn(handle_t *handle, struct buffer_head *bh)
+static int write_end_fn(handle_t *handle, struct inode *inode,
+                       struct buffer_head *bh)
 {
        int ret;
        if (!buffer_mapped(bh) || buffer_freed(bh))
@@ -1352,6 +1354,7 @@ errout:
  * to call ext4_handle_dirty_metadata() instead.
  */
 static void ext4_journalled_zero_new_buffers(handle_t *handle,
+                                           struct inode *inode,
                                            struct page *page,
                                            unsigned from, unsigned to)
 {
@@ -1370,7 +1373,7 @@ static void ext4_journalled_zero_new_buffers(handle_t *handle,
                                        size = min(to, block_end) - start;
 
                                        zero_user(page, start, size);
-                                       write_end_fn(handle, bh);
+                                       write_end_fn(handle, inode, bh);
                                }
                                clear_buffer_new(bh);
                        }
@@ -1412,13 +1415,13 @@ static int ext4_journalled_write_end(struct file *file,
                copied = ret;
        } else if (unlikely(copied < len) && !PageUptodate(page)) {
                copied = 0;
-               ext4_journalled_zero_new_buffers(handle, page, from, to);
+               ext4_journalled_zero_new_buffers(handle, inode, page, from, to);
        } else {
                if (unlikely(copied < len))
-                       ext4_journalled_zero_new_buffers(handle, page,
+                       ext4_journalled_zero_new_buffers(handle, inode, page,
                                                         from + copied, to);
-               ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
-                                            from + copied, &partial,
+               ret = ext4_walk_page_buffers(handle, inode, page_buffers(page),
+                                            from, from + copied, &partial,
                                             write_end_fn);
                if (!partial)
                        SetPageUptodate(page);
@@ -1619,7 +1622,8 @@ static void ext4_print_free_blocks(struct inode *inode)
        return;
 }
 
-static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
+static int ext4_bh_delay_or_unwritten(handle_t *handle, struct inode *inode,
+                                     struct buffer_head *bh)
 {
        return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
 }
@@ -1851,13 +1855,15 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
        return 0;
 }
 
-static int bget_one(handle_t *handle, struct buffer_head *bh)
+static int bget_one(handle_t *handle, struct inode *inode,
+                   struct buffer_head *bh)
 {
        get_bh(bh);
        return 0;
 }
 
-static int bput_one(handle_t *handle, struct buffer_head *bh)
+static int bput_one(handle_t *handle, struct inode *inode,
+                   struct buffer_head *bh)
 {
        put_bh(bh);
        return 0;
@@ -1888,7 +1894,7 @@ static int __ext4_journalled_writepage(struct page *page,
                        BUG();
                        goto out;
                }
-               ext4_walk_page_buffers(handle, page_bufs, 0, len,
+               ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
                                       NULL, bget_one);
        }
        /*
@@ -1920,11 +1926,11 @@ static int __ext4_journalled_writepage(struct page *page,
        if (inline_data) {
                ret = ext4_mark_inode_dirty(handle, inode);
        } else {
-               ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL,
-                                            do_journal_get_write_access);
+               ret = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
+                                            NULL, do_journal_get_write_access);
 
-               err = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL,
-                                            write_end_fn);
+               err = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len,
+                                            NULL, write_end_fn);
        }
        if (ret == 0)
                ret = err;
@@ -1941,7 +1947,7 @@ out:
        unlock_page(page);
 out_no_pagelock:
        if (!inline_data && page_bufs)
-               ext4_walk_page_buffers(NULL, page_bufs, 0, len,
+               ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len,
                                       NULL, bput_one);
        brelse(inode_bh);
        return ret;
@@ -2031,7 +2037,7 @@ static int ext4_writepage(struct page *page,
         * for the extremely common case, this is an optimization that
         * skips a useless round trip through ext4_bio_write_page().
         */
-       if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL,
+       if (ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len, NULL,
                                   ext4_bh_delay_or_unwritten)) {
                redirty_page_for_writepage(wbc, page);
                if ((current->flags & PF_MEMALLOC) ||
@@ -3794,7 +3800,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
        }
        if (ext4_should_journal_data(inode)) {
                BUFFER_TRACE(bh, "get write access");
-               err = ext4_journal_get_write_access(handle, bh);
+               err = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+                                                   EXT4_JTR_NONE);
                if (err)
                        goto unlock;
        }
@@ -4329,101 +4336,93 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
        bh = sb_getblk(sb, block);
        if (unlikely(!bh))
                return -ENOMEM;
-       if (ext4_simulate_fail(sb, EXT4_SIM_INODE_EIO))
-               goto simulate_eio;
-       if (!buffer_uptodate(bh)) {
-               lock_buffer(bh);
+       if (ext4_buffer_uptodate(bh))
+               goto has_buffer;
 
-               if (ext4_buffer_uptodate(bh)) {
-                       /* someone brought it uptodate while we waited */
-                       unlock_buffer(bh);
-                       goto has_buffer;
-               }
-
-               /*
-                * If we have all information of the inode in memory and this
-                * is the only valid inode in the block, we need not read the
-                * block.
-                */
-               if (in_mem) {
-                       struct buffer_head *bitmap_bh;
-                       int i, start;
+       lock_buffer(bh);
+       /*
+        * If we have all information of the inode in memory and this
+        * is the only valid inode in the block, we need not read the
+        * block.
+        */
+       if (in_mem) {
+               struct buffer_head *bitmap_bh;
+               int i, start;
 
-                       start = inode_offset & ~(inodes_per_block - 1);
+               start = inode_offset & ~(inodes_per_block - 1);
 
-                       /* Is the inode bitmap in cache? */
-                       bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
-                       if (unlikely(!bitmap_bh))
-                               goto make_io;
+               /* Is the inode bitmap in cache? */
+               bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
+               if (unlikely(!bitmap_bh))
+                       goto make_io;
 
-                       /*
-                        * If the inode bitmap isn't in cache then the
-                        * optimisation may end up performing two reads instead
-                        * of one, so skip it.
-                        */
-                       if (!buffer_uptodate(bitmap_bh)) {
-                               brelse(bitmap_bh);
-                               goto make_io;
-                       }
-                       for (i = start; i < start + inodes_per_block; i++) {
-                               if (i == inode_offset)
-                                       continue;
-                               if (ext4_test_bit(i, bitmap_bh->b_data))
-                                       break;
-                       }
+               /*
+                * If the inode bitmap isn't in cache then the
+                * optimisation may end up performing two reads instead
+                * of one, so skip it.
+                */
+               if (!buffer_uptodate(bitmap_bh)) {
                        brelse(bitmap_bh);
-                       if (i == start + inodes_per_block) {
-                               /* all other inodes are free, so skip I/O */
-                               memset(bh->b_data, 0, bh->b_size);
-                               set_buffer_uptodate(bh);
-                               unlock_buffer(bh);
-                               goto has_buffer;
-                       }
+                       goto make_io;
                }
+               for (i = start; i < start + inodes_per_block; i++) {
+                       if (i == inode_offset)
+                               continue;
+                       if (ext4_test_bit(i, bitmap_bh->b_data))
+                               break;
+               }
+               brelse(bitmap_bh);
+               if (i == start + inodes_per_block) {
+                       /* all other inodes are free, so skip I/O */
+                       memset(bh->b_data, 0, bh->b_size);
+                       set_buffer_uptodate(bh);
+                       unlock_buffer(bh);
+                       goto has_buffer;
+               }
+       }
 
 make_io:
-               /*
-                * If we need to do any I/O, try to pre-readahead extra
-                * blocks from the inode table.
-                */
-               blk_start_plug(&plug);
-               if (EXT4_SB(sb)->s_inode_readahead_blks) {
-                       ext4_fsblk_t b, end, table;
-                       unsigned num;
-                       __u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
-
-                       table = ext4_inode_table(sb, gdp);
-                       /* s_inode_readahead_blks is always a power of 2 */
-                       b = block & ~((ext4_fsblk_t) ra_blks - 1);
-                       if (table > b)
-                               b = table;
-                       end = b + ra_blks;
-                       num = EXT4_INODES_PER_GROUP(sb);
-                       if (ext4_has_group_desc_csum(sb))
-                               num -= ext4_itable_unused_count(sb, gdp);
-                       table += num / inodes_per_block;
-                       if (end > table)
-                               end = table;
-                       while (b <= end)
-                               ext4_sb_breadahead_unmovable(sb, b++);
-               }
+       /*
+        * If we need to do any I/O, try to pre-readahead extra
+        * blocks from the inode table.
+        */
+       blk_start_plug(&plug);
+       if (EXT4_SB(sb)->s_inode_readahead_blks) {
+               ext4_fsblk_t b, end, table;
+               unsigned num;
+               __u32 ra_blks = EXT4_SB(sb)->s_inode_readahead_blks;
+
+               table = ext4_inode_table(sb, gdp);
+               /* s_inode_readahead_blks is always a power of 2 */
+               b = block & ~((ext4_fsblk_t) ra_blks - 1);
+               if (table > b)
+                       b = table;
+               end = b + ra_blks;
+               num = EXT4_INODES_PER_GROUP(sb);
+               if (ext4_has_group_desc_csum(sb))
+                       num -= ext4_itable_unused_count(sb, gdp);
+               table += num / inodes_per_block;
+               if (end > table)
+                       end = table;
+               while (b <= end)
+                       ext4_sb_breadahead_unmovable(sb, b++);
+       }
 
-               /*
-                * There are other valid inodes in the buffer, this inode
-                * has in-inode xattrs, or we don't have this inode in memory.
-                * Read the block from disk.
-                */
-               trace_ext4_load_inode(sb, ino);
-               ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL);
-               blk_finish_plug(&plug);
-               wait_on_buffer(bh);
-               if (!buffer_uptodate(bh)) {
-               simulate_eio:
-                       if (ret_block)
-                               *ret_block = block;
-                       brelse(bh);
-                       return -EIO;
-               }
+       /*
+        * There are other valid inodes in the buffer, this inode
+        * has in-inode xattrs, or we don't have this inode in memory.
+        * Read the block from disk.
+        */
+       trace_ext4_load_inode(sb, ino);
+       ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL);
+       blk_finish_plug(&plug);
+       wait_on_buffer(bh);
+       ext4_simulate_fail_bh(sb, bh, EXT4_SIM_INODE_EIO);
+       if (!buffer_uptodate(bh)) {
+               if (ret_block)
+                       *ret_block = block;
+               brelse(bh);
+               return -EIO;
        }
 has_buffer:
        iloc->bh = bh;
@@ -4602,6 +4601,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        struct ext4_iloc iloc;
        struct ext4_inode *raw_inode;
        struct ext4_inode_info *ei;
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
        struct inode *inode;
        journal_t *journal = EXT4_SB(sb)->s_journal;
        long ret;
@@ -4612,9 +4612,13 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        projid_t i_projid;
 
        if ((!(flags & EXT4_IGET_SPECIAL) &&
-            (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) ||
+            ((ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ||
+             ino == le32_to_cpu(es->s_usr_quota_inum) ||
+             ino == le32_to_cpu(es->s_grp_quota_inum) ||
+             ino == le32_to_cpu(es->s_prj_quota_inum) ||
+             ino == le32_to_cpu(es->s_orphan_file_inum))) ||
            (ino < EXT4_ROOT_INO) ||
-           (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {
+           (ino > le32_to_cpu(es->s_inodes_count))) {
                if (flags & EXT4_IGET_HANDLE)
                        return ERR_PTR(-ESTALE);
                __ext4_error(sb, function, line, false, EFSCORRUPTED, 0,
@@ -4927,8 +4931,14 @@ static int ext4_inode_blocks_set(handle_t *handle,
                ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
                return 0;
        }
+
+       /*
+        * This should never happen since sb->s_maxbytes should not have
+        * allowed this, sb->s_maxbytes was set according to the huge_file
+        * feature in ext4_fill_super().
+        */
        if (!ext4_has_feature_huge_file(sb))
-               return -EFBIG;
+               return -EFSCORRUPTED;
 
        if (i_blocks <= 0xffffffffffffULL) {
                /*
@@ -5031,16 +5041,14 @@ static int ext4_do_update_inode(handle_t *handle,
 
        spin_lock(&ei->i_raw_lock);
 
-       /* For fields not tracked in the in-memory inode,
-        * initialise them to zero for new inodes. */
+       /*
+        * For fields not tracked in the in-memory inode, initialise them
+        * to zero for new inodes.
+        */
        if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
                memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
 
        err = ext4_inode_blocks_set(handle, raw_inode, ei);
-       if (err) {
-               spin_unlock(&ei->i_raw_lock);
-               goto out_brelse;
-       }
 
        raw_inode->i_mode = cpu_to_le16(inode->i_mode);
        i_uid = i_uid_read(inode);
@@ -5049,10 +5057,11 @@ static int ext4_do_update_inode(handle_t *handle,
        if (!(test_opt(inode->i_sb, NO_UID32))) {
                raw_inode->i_uid_low = cpu_to_le16(low_16_bits(i_uid));
                raw_inode->i_gid_low = cpu_to_le16(low_16_bits(i_gid));
-/*
- * Fix up interoperability with old kernels. Otherwise, old inodes get
- * re-used with the upper 16 bits of the uid/gid intact
- */
+               /*
+                * Fix up interoperability with old kernels. Otherwise,
+                * old inodes get re-used with the upper 16 bits of the
+                * uid/gid intact.
+                */
                if (ei->i_dtime && list_empty(&ei->i_orphan)) {
                        raw_inode->i_uid_high = 0;
                        raw_inode->i_gid_high = 0;
@@ -5121,8 +5130,9 @@ static int ext4_do_update_inode(handle_t *handle,
                }
        }
 
-       BUG_ON(!ext4_has_feature_project(inode->i_sb) &&
-              i_projid != EXT4_DEF_PROJID);
+       if (i_projid != EXT4_DEF_PROJID &&
+           !ext4_has_feature_project(inode->i_sb))
+               err = err ?: -EFSCORRUPTED;
 
        if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
            EXT4_FITS_IN_INODE(raw_inode, ei, i_projid))
@@ -5130,6 +5140,11 @@ static int ext4_do_update_inode(handle_t *handle,
 
        ext4_inode_csum_set(inode, raw_inode, ei);
        spin_unlock(&ei->i_raw_lock);
+       if (err) {
+               EXT4_ERROR_INODE(inode, "corrupted inode contents");
+               goto out_brelse;
+       }
+
        if (inode->i_sb->s_flags & SB_LAZYTIME)
                ext4_update_other_inodes_time(inode->i_sb, inode->i_ino,
                                              bh->b_data);
@@ -5137,13 +5152,15 @@ static int ext4_do_update_inode(handle_t *handle,
        BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, bh);
        if (err)
-               goto out_brelse;
+               goto out_error;
        ext4_clear_inode_state(inode, EXT4_STATE_NEW);
        if (set_large_file) {
                BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get write access");
-               err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
+               err = ext4_journal_get_write_access(handle, sb,
+                                                   EXT4_SB(sb)->s_sbh,
+                                                   EXT4_JTR_NONE);
                if (err)
-                       goto out_brelse;
+                       goto out_error;
                lock_buffer(EXT4_SB(sb)->s_sbh);
                ext4_set_feature_large_file(sb);
                ext4_superblock_csum_set(sb);
@@ -5153,9 +5170,10 @@ static int ext4_do_update_inode(handle_t *handle,
                                                 EXT4_SB(sb)->s_sbh);
        }
        ext4_update_inode_fsync_trans(handle, inode, need_datasync);
+out_error:
+       ext4_std_error(inode->i_sb, err);
 out_brelse:
        brelse(bh);
-       ext4_std_error(inode->i_sb, err);
        return err;
 }
 
@@ -5742,7 +5760,8 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode,
        err = ext4_get_inode_loc(inode, iloc);
        if (!err) {
                BUFFER_TRACE(iloc->bh, "get_write_access");
-               err = ext4_journal_get_write_access(handle, iloc->bh);
+               err = ext4_journal_get_write_access(handle, inode->i_sb,
+                                                   iloc->bh, EXT4_JTR_NONE);
                if (err) {
                        brelse(iloc->bh);
                        iloc->bh = NULL;
@@ -5865,7 +5884,8 @@ int ext4_expand_extra_isize(struct inode *inode,
        ext4_write_lock_xattr(inode, &no_expand);
 
        BUFFER_TRACE(iloc->bh, "get_write_access");
-       error = ext4_journal_get_write_access(handle, iloc->bh);
+       error = ext4_journal_get_write_access(handle, inode->i_sb, iloc->bh,
+                                             EXT4_JTR_NONE);
        if (error) {
                brelse(iloc->bh);
                goto out_unlock;
@@ -6036,7 +6056,8 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        return err;
 }
 
-static int ext4_bh_unmapped(handle_t *handle, struct buffer_head *bh)
+static int ext4_bh_unmapped(handle_t *handle, struct inode *inode,
+                           struct buffer_head *bh)
 {
        return !buffer_mapped(bh);
 }
@@ -6109,7 +6130,7 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
         * inode to the transaction's list to writeprotect pages on commit.
         */
        if (page_has_buffers(page)) {
-               if (!ext4_walk_page_buffers(NULL, page_buffers(page),
+               if (!ext4_walk_page_buffers(NULL, inode, page_buffers(page),
                                            0, len, NULL,
                                            ext4_bh_unmapped)) {
                        /* Wait so that we don't change page under IO */
@@ -6155,11 +6176,13 @@ retry_alloc:
                err = __block_write_begin(page, 0, len, ext4_get_block);
                if (!err) {
                        ret = VM_FAULT_SIGBUS;
-                       if (ext4_walk_page_buffers(handle, page_buffers(page),
-                                       0, len, NULL, do_journal_get_write_access))
+                       if (ext4_walk_page_buffers(handle, inode,
+                                       page_buffers(page), 0, len, NULL,
+                                       do_journal_get_write_access))
                                goto out_error;
-                       if (ext4_walk_page_buffers(handle, page_buffers(page),
-                                       0, len, NULL, write_end_fn))
+                       if (ext4_walk_page_buffers(handle, inode,
+                                       page_buffers(page), 0, len, NULL,
+                                       write_end_fn))
                                goto out_error;
                        if (ext4_jbd2_inode_add_write(handle, inode,
                                                      page_offset(page), len))