lkml.org 
[lkml]   [2009]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 47/49] ext4: Avoid leaking blocks after a block allocation failure
    Date
    From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

    We should add inode to the orphan list in the same transaction
    as block allocation. This ensures that if we crash after a failed
    block allocation and before we do a vmtruncate we don't leak block
    (ie block marked as used in bitmap but not claimed by the inode).

    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    CC: Jan Kara <jack@suse.cz>
    Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
    ---
    fs/ext4/inode.c | 24 ++++++++++++++++++++++--
    1 files changed, 22 insertions(+), 2 deletions(-)

    diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
    index 95a3f45..036552a 100644
    --- a/fs/ext4/inode.c
    +++ b/fs/ext4/inode.c
    @@ -1462,7 +1462,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
    struct page **pagep, void **fsdata)
    {
    struct inode *inode = mapping->host;
    - int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
    + int ret, needed_blocks;
    handle_t *handle;
    int retries = 0;
    struct page *page;
    @@ -1473,6 +1473,11 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
    "dev %s ino %lu pos %llu len %u flags %u",
    inode->i_sb->s_id, inode->i_ino,
    (unsigned long long) pos, len, flags);
    + /*
    + * Reserve one block more for addition to orphan list in case
    + * we allocate blocks but write fails for some reason
    + */
    + needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
    index = pos >> PAGE_CACHE_SHIFT;
    from = pos & (PAGE_CACHE_SIZE - 1);
    to = from + len;
    @@ -1506,15 +1511,30 @@ retry:

    if (ret) {
    unlock_page(page);
    - ext4_journal_stop(handle);
    page_cache_release(page);
    /*
    * block_write_begin may have instantiated a few blocks
    * outside i_size. Trim these off again. Don't need
    * i_size_read because we hold i_mutex.
    + *
    + * Add inode to orphan list in case we crash before
    + * truncate finishes
    */
    if (pos + len > inode->i_size)
    + ext4_orphan_add(handle, inode);
    +
    + ext4_journal_stop(handle);
    + if (pos + len > inode->i_size) {
    vmtruncate(inode, inode->i_size);
    + /*
    + * If vmtruncate failed early the inode might
    + * still be on the orphan list; we need to
    + * make sure the inode is removed from the
    + * orphan list in that case.
    + */
    + if (inode->i_nlink)
    + ext4_orphan_del(NULL, inode);
    + }
    }

    if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
    --
    1.6.3.2.1.gb9f7d.dirty


    \
     
     \ /
      Last update: 2009-06-08 21:39    [W:4.267 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site