aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/balloc.c2
-rw-r--r--fs/ext4/extents.c14
-rw-r--r--fs/ext4/inode.c85
-rw-r--r--fs/ext4/xattr.c41
4 files changed, 43 insertions, 99 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index c4dd1103ccf1..8a23483ca8d0 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -50,7 +50,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
50 * The file system contains group descriptors which are located after the 50 * The file system contains group descriptors which are located after the
51 * super block. Each descriptor contains the number of the bitmap block and 51 * super block. Each descriptor contains the number of the bitmap block and
52 * the free blocks count in the block. The descriptors are loaded in memory 52 * the free blocks count in the block. The descriptors are loaded in memory
53 * when a file system is mounted (see ext4_read_super). 53 * when a file system is mounted (see ext4_fill_super).
54 */ 54 */
55 55
56 56
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index dc2724fa7622..7916b50f9a13 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -222,7 +222,7 @@ static int ext4_ext_space_block(struct inode *inode)
222 222
223 size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) 223 size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
224 / sizeof(struct ext4_extent); 224 / sizeof(struct ext4_extent);
225#ifdef AGRESSIVE_TEST 225#ifdef AGGRESSIVE_TEST
226 if (size > 6) 226 if (size > 6)
227 size = 6; 227 size = 6;
228#endif 228#endif
@@ -235,7 +235,7 @@ static int ext4_ext_space_block_idx(struct inode *inode)
235 235
236 size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) 236 size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
237 / sizeof(struct ext4_extent_idx); 237 / sizeof(struct ext4_extent_idx);
238#ifdef AGRESSIVE_TEST 238#ifdef AGGRESSIVE_TEST
239 if (size > 5) 239 if (size > 5)
240 size = 5; 240 size = 5;
241#endif 241#endif
@@ -249,7 +249,7 @@ static int ext4_ext_space_root(struct inode *inode)
249 size = sizeof(EXT4_I(inode)->i_data); 249 size = sizeof(EXT4_I(inode)->i_data);
250 size -= sizeof(struct ext4_extent_header); 250 size -= sizeof(struct ext4_extent_header);
251 size /= sizeof(struct ext4_extent); 251 size /= sizeof(struct ext4_extent);
252#ifdef AGRESSIVE_TEST 252#ifdef AGGRESSIVE_TEST
253 if (size > 3) 253 if (size > 3)
254 size = 3; 254 size = 3;
255#endif 255#endif
@@ -263,7 +263,7 @@ static int ext4_ext_space_root_idx(struct inode *inode)
263 size = sizeof(EXT4_I(inode)->i_data); 263 size = sizeof(EXT4_I(inode)->i_data);
264 size -= sizeof(struct ext4_extent_header); 264 size -= sizeof(struct ext4_extent_header);
265 size /= sizeof(struct ext4_extent_idx); 265 size /= sizeof(struct ext4_extent_idx);
266#ifdef AGRESSIVE_TEST 266#ifdef AGGRESSIVE_TEST
267 if (size > 4) 267 if (size > 4)
268 size = 4; 268 size = 4;
269#endif 269#endif
@@ -1118,7 +1118,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
1118 */ 1118 */
1119 if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN) 1119 if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN)
1120 return 0; 1120 return 0;
1121#ifdef AGRESSIVE_TEST 1121#ifdef AGGRESSIVE_TEST
1122 if (le16_to_cpu(ex1->ee_len) >= 4) 1122 if (le16_to_cpu(ex1->ee_len) >= 4)
1123 return 0; 1123 return 0;
1124#endif 1124#endif
@@ -1891,8 +1891,8 @@ void ext4_ext_init(struct super_block *sb)
1891 1891
1892 if (test_opt(sb, EXTENTS)) { 1892 if (test_opt(sb, EXTENTS)) {
1893 printk("EXT4-fs: file extents enabled"); 1893 printk("EXT4-fs: file extents enabled");
1894#ifdef AGRESSIVE_TEST 1894#ifdef AGGRESSIVE_TEST
1895 printk(", agressive tests"); 1895 printk(", aggressive tests");
1896#endif 1896#endif
1897#ifdef CHECK_BINSEARCH 1897#ifdef CHECK_BINSEARCH
1898 printk(", check binsearch"); 1898 printk(", check binsearch");
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index fbff4b9e122a..810b6d6474bf 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1147,102 +1147,37 @@ static int do_journal_get_write_access(handle_t *handle,
1147 return ext4_journal_get_write_access(handle, bh); 1147 return ext4_journal_get_write_access(handle, bh);
1148} 1148}
1149 1149
1150/*
1151 * The idea of this helper function is following:
1152 * if prepare_write has allocated some blocks, but not all of them, the
1153 * transaction must include the content of the newly allocated blocks.
1154 * This content is expected to be set to zeroes by block_prepare_write().
1155 * 2006/10/14 SAW
1156 */
1157static int ext4_prepare_failure(struct file *file, struct page *page,
1158 unsigned from, unsigned to)
1159{
1160 struct address_space *mapping;
1161 struct buffer_head *bh, *head, *next;
1162 unsigned block_start, block_end;
1163 unsigned blocksize;
1164 int ret;
1165 handle_t *handle = ext4_journal_current_handle();
1166
1167 mapping = page->mapping;
1168 if (ext4_should_writeback_data(mapping->host)) {
1169 /* optimization: no constraints about data */
1170skip:
1171 return ext4_journal_stop(handle);
1172 }
1173
1174 head = page_buffers(page);
1175 blocksize = head->b_size;
1176 for ( bh = head, block_start = 0;
1177 bh != head || !block_start;
1178 block_start = block_end, bh = next)
1179 {
1180 next = bh->b_this_page;
1181 block_end = block_start + blocksize;
1182 if (block_end <= from)
1183 continue;
1184 if (block_start >= to) {
1185 block_start = to;
1186 break;
1187 }
1188 if (!buffer_mapped(bh))
1189 /* prepare_write failed on this bh */
1190 break;
1191 if (ext4_should_journal_data(mapping->host)) {
1192 ret = do_journal_get_write_access(handle, bh);
1193 if (ret) {
1194 ext4_journal_stop(handle);
1195 return ret;
1196 }
1197 }
1198 /*
1199 * block_start here becomes the first block where the current iteration
1200 * of prepare_write failed.
1201 */
1202 }
1203 if (block_start <= from)
1204 goto skip;
1205
1206 /* commit allocated and zeroed buffers */
1207 return mapping->a_ops->commit_write(file, page, from, block_start);
1208}
1209
1210static int ext4_prepare_write(struct file *file, struct page *page, 1150static int ext4_prepare_write(struct file *file, struct page *page,
1211 unsigned from, unsigned to) 1151 unsigned from, unsigned to)
1212{ 1152{
1213 struct inode *inode = page->mapping->host; 1153 struct inode *inode = page->mapping->host;
1214 int ret, ret2; 1154 int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
1215 int needed_blocks = ext4_writepage_trans_blocks(inode);
1216 handle_t *handle; 1155 handle_t *handle;
1217 int retries = 0; 1156 int retries = 0;
1218 1157
1219retry: 1158retry:
1220 handle = ext4_journal_start(inode, needed_blocks); 1159 handle = ext4_journal_start(inode, needed_blocks);
1221 if (IS_ERR(handle)) 1160 if (IS_ERR(handle)) {
1222 return PTR_ERR(handle); 1161 ret = PTR_ERR(handle);
1162 goto out;
1163 }
1223 if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) 1164 if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
1224 ret = nobh_prepare_write(page, from, to, ext4_get_block); 1165 ret = nobh_prepare_write(page, from, to, ext4_get_block);
1225 else 1166 else
1226 ret = block_prepare_write(page, from, to, ext4_get_block); 1167 ret = block_prepare_write(page, from, to, ext4_get_block);
1227 if (ret) 1168 if (ret)
1228 goto failure; 1169 goto prepare_write_failed;
1229 1170
1230 if (ext4_should_journal_data(inode)) { 1171 if (ext4_should_journal_data(inode)) {
1231 ret = walk_page_buffers(handle, page_buffers(page), 1172 ret = walk_page_buffers(handle, page_buffers(page),
1232 from, to, NULL, do_journal_get_write_access); 1173 from, to, NULL, do_journal_get_write_access);
1233 if (ret)
1234 /* fatal error, just put the handle and return */
1235 ext4_journal_stop(handle);
1236 } 1174 }
1237 return ret; 1175prepare_write_failed:
1238 1176 if (ret)
1239failure: 1177 ext4_journal_stop(handle);
1240 ret2 = ext4_prepare_failure(file, page, from, to);
1241 if (ret2 < 0)
1242 return ret2;
1243 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 1178 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
1244 goto retry; 1179 goto retry;
1245 /* retry number exceeded, or other error like -EDQUOT */ 1180out:
1246 return ret; 1181 return ret;
1247} 1182}
1248 1183
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index dc969c357aa1..e832e96095b3 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -475,8 +475,14 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
475 struct buffer_head *bh) 475 struct buffer_head *bh)
476{ 476{
477 struct mb_cache_entry *ce = NULL; 477 struct mb_cache_entry *ce = NULL;
478 int error = 0;
478 479
479 ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr); 480 ce = mb_cache_entry_get(ext4_xattr_cache, bh->b_bdev, bh->b_blocknr);
481 error = ext4_journal_get_write_access(handle, bh);
482 if (error)
483 goto out;
484
485 lock_buffer(bh);
480 if (BHDR(bh)->h_refcount == cpu_to_le32(1)) { 486 if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
481 ea_bdebug(bh, "refcount now=0; freeing"); 487 ea_bdebug(bh, "refcount now=0; freeing");
482 if (ce) 488 if (ce)
@@ -485,21 +491,21 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
485 get_bh(bh); 491 get_bh(bh);
486 ext4_forget(handle, 1, inode, bh, bh->b_blocknr); 492 ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
487 } else { 493 } else {
488 if (ext4_journal_get_write_access(handle, bh) == 0) { 494 BHDR(bh)->h_refcount = cpu_to_le32(
489 lock_buffer(bh);
490 BHDR(bh)->h_refcount = cpu_to_le32(
491 le32_to_cpu(BHDR(bh)->h_refcount) - 1); 495 le32_to_cpu(BHDR(bh)->h_refcount) - 1);
492 ext4_journal_dirty_metadata(handle, bh); 496 error = ext4_journal_dirty_metadata(handle, bh);
493 if (IS_SYNC(inode)) 497 if (IS_SYNC(inode))
494 handle->h_sync = 1; 498 handle->h_sync = 1;
495 DQUOT_FREE_BLOCK(inode, 1); 499 DQUOT_FREE_BLOCK(inode, 1);
496 unlock_buffer(bh); 500 ea_bdebug(bh, "refcount now=%d; releasing",
497 ea_bdebug(bh, "refcount now=%d; releasing", 501 le32_to_cpu(BHDR(bh)->h_refcount));
498 le32_to_cpu(BHDR(bh)->h_refcount));
499 }
500 if (ce) 502 if (ce)
501 mb_cache_entry_release(ce); 503 mb_cache_entry_release(ce);
502 } 504 }
505 unlock_buffer(bh);
506out:
507 ext4_std_error(inode->i_sb, error);
508 return;
503} 509}
504 510
505struct ext4_xattr_info { 511struct ext4_xattr_info {
@@ -675,7 +681,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
675 struct buffer_head *new_bh = NULL; 681 struct buffer_head *new_bh = NULL;
676 struct ext4_xattr_search *s = &bs->s; 682 struct ext4_xattr_search *s = &bs->s;
677 struct mb_cache_entry *ce = NULL; 683 struct mb_cache_entry *ce = NULL;
678 int error; 684 int error = 0;
679 685
680#define header(x) ((struct ext4_xattr_header *)(x)) 686#define header(x) ((struct ext4_xattr_header *)(x))
681 687
@@ -684,16 +690,17 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
684 if (s->base) { 690 if (s->base) {
685 ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev, 691 ce = mb_cache_entry_get(ext4_xattr_cache, bs->bh->b_bdev,
686 bs->bh->b_blocknr); 692 bs->bh->b_blocknr);
693 error = ext4_journal_get_write_access(handle, bs->bh);
694 if (error)
695 goto cleanup;
696 lock_buffer(bs->bh);
697
687 if (header(s->base)->h_refcount == cpu_to_le32(1)) { 698 if (header(s->base)->h_refcount == cpu_to_le32(1)) {
688 if (ce) { 699 if (ce) {
689 mb_cache_entry_free(ce); 700 mb_cache_entry_free(ce);
690 ce = NULL; 701 ce = NULL;
691 } 702 }
692 ea_bdebug(bs->bh, "modifying in-place"); 703 ea_bdebug(bs->bh, "modifying in-place");
693 error = ext4_journal_get_write_access(handle, bs->bh);
694 if (error)
695 goto cleanup;
696 lock_buffer(bs->bh);
697 error = ext4_xattr_set_entry(i, s); 704 error = ext4_xattr_set_entry(i, s);
698 if (!error) { 705 if (!error) {
699 if (!IS_LAST_ENTRY(s->first)) 706 if (!IS_LAST_ENTRY(s->first))
@@ -713,6 +720,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
713 } else { 720 } else {
714 int offset = (char *)s->here - bs->bh->b_data; 721 int offset = (char *)s->here - bs->bh->b_data;
715 722
723 unlock_buffer(bs->bh);
724 jbd2_journal_release_buffer(handle, bs->bh);
716 if (ce) { 725 if (ce) {
717 mb_cache_entry_release(ce); 726 mb_cache_entry_release(ce);
718 ce = NULL; 727 ce = NULL;