From 9cb00419faa7dd81e921328a71931d2b95ed5876 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Mon, 6 Jan 2014 14:01:23 -0500 Subject: ext4: enable punch hole for bigalloc After applied this commit (d23142c6), ext4 has supported punch hole for a file system with bigalloc feature. But we forgot to enable it. This commit fixes it. Cc: Lukas Czerner Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 61d49ff22c81..90a4ea781cd4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3501,11 +3501,6 @@ 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); /* -- cgit v1.2.3 From bc0ca9df3b2abb13f7da9d8d255ec60718badd84 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 6 Jan 2014 14:02:23 -0500 Subject: ext4: retry allocation when inline->extent conversion failed Similarly as other ->write_begin functions in ext4, also ext4_da_write_inline_data_begin() should retry allocation if the conversion failed because of ENOSPC. This avoids returning ENOSPC prematurely because of uncommitted block deletions. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" --- fs/ext4/inline.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/ext4') diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index bae987549dc3..ed6e71fe5e9d 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -849,11 +849,13 @@ 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); @@ -875,6 +877,11 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping, inode, flags, fsdata); + ext4_journal_stop(handle); + handle = NULL; + if (ret == -ENOSPC && + ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry_journal; goto out; } -- cgit v1.2.3 From 52e4477758eef45c2fa28b087abf83847126bc28 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 6 Jan 2014 14:03:23 -0500 Subject: ext4: standardize error handling in ext4_da_write_inline_data_begin() The function has a bit non-standard (for ext4) error recovery in that it used a mix of 'out' labels and testing for 'handle' being NULL. There isn't a good reason for that in the function so clean it up a bit. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" --- fs/ext4/inline.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index ed6e71fe5e9d..c417e52d194e 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -859,7 +859,6 @@ retry_journal: handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); if (IS_ERR(handle)) { ret = PTR_ERR(handle); - handle = NULL; goto out; } @@ -869,7 +868,7 @@ retry_journal: 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) { @@ -878,7 +877,6 @@ retry_journal: flags, fsdata); ext4_journal_stop(handle); - handle = NULL; if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) goto retry_journal; @@ -894,7 +892,7 @@ retry_journal: 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); @@ -911,16 +909,15 @@ retry_journal: 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; } -- cgit v1.2.3 From a34e15cc35c743f0e49125a4fbd22a7c55b686d8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 6 Jan 2014 14:04:23 -0500 Subject: ext4: use %pd printk specificer Use the new %pd printk() specifier in Ext4 to replace passing of dentry name or dentry name and name length * 2 with just passing the dentry. Signed-off-by: David Howells Signed-off-by: "Theodore Ts'o" cc: Andreas Dilger cc: linux-ext4@vger.kernel.org --- fs/ext4/namei.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5a0408d7b114..3e9e70663233 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1425,9 +1425,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi return ERR_PTR(-EIO); } if (unlikely(ino == dir->i_ino)) { - EXT4_ERROR_INODE(dir, "'%.*s' linked to parent dir", - dentry->d_name.len, - dentry->d_name.name); + EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir", + dentry); return ERR_PTR(-EIO); } inode = ext4_iget(dir->i_sb, ino); -- cgit v1.2.3 From 9e740568bc65a82845330b9439514255140b94aa Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Mon, 6 Jan 2014 14:05:23 -0500 Subject: ext4: fix a typo in extents.c Signed-off-by: Yongqiang Yang Reviewed-by: Carlos Maiolino --- fs/ext4/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext4') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 3384dc4bed40..10cff4736b11 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3477,7 +3477,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, WARN_ON(map->m_lblk < ee_block); /* * It is safe to convert extent to initialized via explicit - * zeroout only if extent is fully insde i_size or new_size. + * zeroout only if extent is fully inside i_size or new_size. */ split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; -- cgit v1.2.3 From 65eddb56f465f314502679ceade6fc5848a53a50 Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Mon, 6 Jan 2014 14:06:18 -0500 Subject: ext4: ext4_inode_is_fast_symlink should use EXT4_CLUSTER_SIZE Can be reproduced by xfstests 62 with bigalloc and 128bit size inode. Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" Reviewed-by: Carlos Maiolino --- fs/ext4/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 90a4ea781cd4..8454ebe238a0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -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); } -- cgit v1.2.3 From 09c455aaa8f47a94d5bafaa23d58365768210507 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 7 Jan 2014 12:58:19 -0500 Subject: ext4: avoid clearing beyond i_blocks when truncating an inline data file A missing cast means that when we are truncating a file which is less than 60 bytes, we don't clear the correct area of memory, and in fact we can end up truncating the next inode in the inode table, or worse yet, some other kernel data structure. Addresses-Coverity-Id: #751987 Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/inline.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index c417e52d194e..ed29e720e880 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1928,9 +1928,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 ? -- cgit v1.2.3 From 8c9367fd9bf252b57c6d4f8e1a7f9de809d8b862 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 7 Jan 2014 13:08:03 -0500 Subject: ext4: don't pass freed handle to ext4_walk_page_buffers This is harmless, since ext4_walk_page_buffers only passes the handle onto the callback function, and in this call site the function in question, bput_one(), doesn't actually use the handle. But there's no point passing in an invalid handle, and it creates a Coverity warning, so let's just clean it up. Addresses-Coverity-Id: #1091168 Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8454ebe238a0..f33b4eb82d80 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1772,7 +1772,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: -- cgit v1.2.3 From d7092ae2973f20a39fee786c47e5edf18ced088f Mon Sep 17 00:00:00 2001 From: jon ernst Date: Sat, 11 Jan 2014 13:26:56 -0500 Subject: ext4: delete "set but not used" variables Signed-off-by: Jon Ernst Signed-off-by: "Theodore Ts'o" Reviewed-by: Zheng Liu --- fs/ext4/inline.c | 2 -- fs/ext4/ioctl.c | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'fs/ext4') diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index ed29e720e880..82edf5b93352 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1841,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; @@ -1850,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) + diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 60589b60e9b0..6bea80614d77 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -101,9 +101,8 @@ static long swap_inode_boot_loader(struct super_block *sb, handle_t *handle; int err; struct inode *inode_bl; - struct ext4_inode_info *ei; struct ext4_inode_info *ei_bl; - struct ext4_sb_info *sbi; + struct ext4_sb_info *sbi = EXT4_SB(sb); if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) { err = -EINVAL; @@ -115,9 +114,6 @@ static long swap_inode_boot_loader(struct super_block *sb, goto swap_boot_out; } - sbi = EXT4_SB(sb); - ei = EXT4_I(inode); - inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO); if (IS_ERR(inode_bl)) { err = PTR_ERR(inode_bl); -- cgit v1.2.3