ext4: kill i_version support for Hurd-castrated file systems
[cascardo/linux.git] / fs / ext4 / inode.c
index 31fa964..ed2c13a 100644 (file)
@@ -144,8 +144,8 @@ static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
  */
 static int ext4_inode_is_fast_symlink(struct inode *inode)
 {
-       int ea_blocks = EXT4_I(inode)->i_file_acl ?
-               (inode->i_sb->s_blocksize >> 9) : 0;
+        int ea_blocks = EXT4_I(inode)->i_file_acl ?
+               EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;
 
        return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
 }
@@ -503,6 +503,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 {
        struct extent_status es;
        int retval;
+       int ret = 0;
 #ifdef ES_AGGRESSIVE_TEST
        struct ext4_map_blocks orig_map;
 
@@ -514,6 +515,12 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                  "logical block %lu\n", inode->i_ino, flags, map->m_len,
                  (unsigned long) map->m_lblk);
 
+       /*
+        * ext4_map_blocks returns an int, and m_len is an unsigned int
+        */
+       if (unlikely(map->m_len > INT_MAX))
+               map->m_len = INT_MAX;
+
        /* Lookup extent status tree firstly */
        if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
                ext4_es_lru_add(inode);
@@ -552,7 +559,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                                             EXT4_GET_BLOCKS_KEEP_SIZE);
        }
        if (retval > 0) {
-               int ret;
                unsigned int status;
 
                if (unlikely(retval != map->m_len)) {
@@ -579,7 +585,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 
 found:
        if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
-               int ret = check_block_validity(inode, map);
+               ret = check_block_validity(inode, map);
                if (ret != 0)
                        return ret;
        }
@@ -596,7 +602,13 @@ found:
         * with buffer head unmapped.
         */
        if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
-               return retval;
+               /*
+                * If we need to convert extent to unwritten
+                * we continue and do the actual work in
+                * ext4_ext_map_blocks()
+                */
+               if (!(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))
+                       return retval;
 
        /*
         * Here we clear m_flags because after allocating an new extent,
@@ -652,7 +664,6 @@ found:
                ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
 
        if (retval > 0) {
-               int ret;
                unsigned int status;
 
                if (unlikely(retval != map->m_len)) {
@@ -687,7 +698,7 @@ found:
 has_zeroout:
        up_write((&EXT4_I(inode)->i_data_sem));
        if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
-               int ret = check_block_validity(inode, map);
+               ret = check_block_validity(inode, map);
                if (ret != 0)
                        return ret;
        }
@@ -1772,7 +1783,7 @@ static int __ext4_journalled_writepage(struct page *page,
                ret = err;
 
        if (!ext4_has_inline_data(inode))
-               ext4_walk_page_buffers(handle, page_bufs, 0, len,
+               ext4_walk_page_buffers(NULL, page_bufs, 0, len,
                                       NULL, bput_one);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 out:
@@ -3501,12 +3512,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
        if (!S_ISREG(inode->i_mode))
                return -EOPNOTSUPP;
 
-       if (EXT4_SB(sb)->s_cluster_ratio > 1) {
-               /* TODO: Add support for bigalloc file systems */
-               return -EOPNOTSUPP;
-       }
-
-       trace_ext4_punch_hole(inode, offset, length);
+       trace_ext4_punch_hole(inode, offset, length, 0);
 
        /*
         * Write out all dirty pages to avoid race conditions
@@ -3613,6 +3619,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
        up_write(&EXT4_I(inode)->i_data_sem);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
+
+       /* Now release the pages again to reduce race window */
+       if (last_block_offset > first_block_offset)
+               truncate_pagecache_range(inode, first_block_offset,
+                                        last_block_offset);
+
        inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
        ext4_mark_inode_dirty(handle, inode);
 out_stop:
@@ -4156,11 +4168,14 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
        EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
        EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
 
-       inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
-       if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
-               if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
-                       inode->i_version |=
-                       (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
+       if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+           cpu_to_le32(EXT4_OS_HURD)) {
+               inode->i_version = le32_to_cpu(raw_inode->i_disk_version);
+               if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+                       if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+                               inode->i_version |=
+                   (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
+               }
        }
 
        ret = 0;
@@ -4376,12 +4391,16 @@ static int ext4_do_update_inode(handle_t *handle,
                        raw_inode->i_block[block] = ei->i_data[block];
        }
 
-       raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
-       if (ei->i_extra_isize) {
-               if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
-                       raw_inode->i_version_hi =
-                       cpu_to_le32(inode->i_version >> 32);
-               raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
+       if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
+           cpu_to_le32(EXT4_OS_HURD)) {
+               raw_inode->i_disk_version = cpu_to_le32(inode->i_version);
+               if (ei->i_extra_isize) {
+                       if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi))
+                               raw_inode->i_version_hi =
+                                       cpu_to_le32(inode->i_version >> 32);
+                       raw_inode->i_extra_isize =
+                               cpu_to_le16(ei->i_extra_isize);
+               }
        }
 
        ext4_inode_csum_set(inode, raw_inode, ei);
@@ -4448,7 +4467,12 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
                        return -EIO;
                }
 
-               if (wbc->sync_mode != WB_SYNC_ALL)
+               /*
+                * No need to force transaction in WB_SYNC_NONE mode. Also
+                * ext4_sync_fs() will force the commit after everything is
+                * written.
+                */
+               if (wbc->sync_mode != WB_SYNC_ALL || wbc->for_sync)
                        return 0;
 
                err = ext4_force_commit(inode->i_sb);
@@ -4458,7 +4482,11 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
                err = __ext4_get_inode_loc(inode, &iloc, 0);
                if (err)
                        return err;
-               if (wbc->sync_mode == WB_SYNC_ALL)
+               /*
+                * sync(2) will flush the whole buffer cache. No need to do
+                * it here separately for each inode.
+                */
+               if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
                        sync_dirty_buffer(iloc.bh);
                if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
                        EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
@@ -4667,7 +4695,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                ext4_orphan_del(NULL, inode);
 
        if (!rc && (ia_valid & ATTR_MODE))
-               rc = ext4_acl_chmod(inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
 
 err_out:
        ext4_std_error(inode->i_sb, error);