]> Pileus Git - ~andy/linux/blobdiff - fs/ext4/inline.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome...
[~andy/linux] / fs / ext4 / inline.c
index bae987549dc367736eaf0beeedb29e8e514e46e6..82edf5b9335277b8f508be2105b6944a9d57ce5c 100644 (file)
@@ -849,15 +849,16 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        handle_t *handle;
        struct page *page;
        struct ext4_iloc iloc;
+       int retries;
 
        ret = ext4_get_inode_loc(inode, &iloc);
        if (ret)
                return ret;
 
+retry_journal:
        handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
-               handle = NULL;
                goto out;
        }
 
@@ -867,7 +868,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        if (inline_size >= pos + len) {
                ret = ext4_prepare_inline_data(handle, inode, pos + len);
                if (ret && ret != -ENOSPC)
-                       goto out;
+                       goto out_journal;
        }
 
        if (ret == -ENOSPC) {
@@ -875,6 +876,10 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
                                                            inode,
                                                            flags,
                                                            fsdata);
+               ext4_journal_stop(handle);
+               if (ret == -ENOSPC &&
+                   ext4_should_retry_alloc(inode->i_sb, &retries))
+                       goto retry_journal;
                goto out;
        }
 
@@ -887,7 +892,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        page = grab_cache_page_write_begin(mapping, 0, flags);
        if (!page) {
                ret = -ENOMEM;
-               goto out;
+               goto out_journal;
        }
 
        down_read(&EXT4_I(inode)->xattr_sem);
@@ -904,16 +909,15 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
 
        up_read(&EXT4_I(inode)->xattr_sem);
        *pagep = page;
-       handle = NULL;
        brelse(iloc.bh);
        return 1;
 out_release_page:
        up_read(&EXT4_I(inode)->xattr_sem);
        unlock_page(page);
        page_cache_release(page);
+out_journal:
+       ext4_journal_stop(handle);
 out:
-       if (handle)
-               ext4_journal_stop(handle);
        brelse(iloc.bh);
        return ret;
 }
@@ -1837,7 +1841,6 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
 {
        int error;
        struct ext4_xattr_entry *entry;
-       struct ext4_xattr_ibody_header *header;
        struct ext4_inode *raw_inode;
        struct ext4_iloc iloc;
 
@@ -1846,7 +1849,6 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
                return error;
 
        raw_inode = ext4_raw_inode(&iloc);
-       header = IHDR(inode, raw_inode);
        entry = (struct ext4_xattr_entry *)((void *)raw_inode +
                                            EXT4_I(inode)->i_inline_off);
        if (EXT4_XATTR_LEN(entry->e_name_len) +
@@ -1924,9 +1926,11 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
                }
 
                /* Clear the content within i_blocks. */
-               if (i_size < EXT4_MIN_INLINE_DATA_SIZE)
-                       memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0,
-                                       EXT4_MIN_INLINE_DATA_SIZE - i_size);
+               if (i_size < EXT4_MIN_INLINE_DATA_SIZE) {
+                       void *p = (void *) ext4_raw_inode(&is.iloc)->i_block;
+                       memset(p + i_size, 0,
+                              EXT4_MIN_INLINE_DATA_SIZE - i_size);
+               }
 
                EXT4_I(inode)->i_inline_size = i_size <
                                        EXT4_MIN_INLINE_DATA_SIZE ?