]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: Jan Kara <jack@suse.cz> |
2 | Subject: reiserfs: Truncate blocks not used by a write | |
3 | References: bnc#483375 | |
4 | Patch-mainline: 2.6.32 | |
5 | ||
6 | It can happen that write does not use all the blocks allocated in write_begin | |
7 | either because of some filesystem error (like ENOSPC) or because page with | |
8 | data to write has been removed from memory. We truncate these blocks so that | |
9 | we don't have dangling blocks beyond i_size. | |
10 | ||
11 | Signed-off-by: Jan Kara <jack@suse.cz> | |
12 | ||
13 | diff -rupX /home/jack/.kerndiffexclude linux-2.6.27-SLE11_BRANCH/fs/reiserfs/inode.c linux-2.6.27-SLE11_BRANCH-1-reiserfs_corruption/fs/reiserfs/inode.c | |
14 | --- linux-2.6.27-SLE11_BRANCH/fs/reiserfs/inode.c 2009-06-02 17:14:29.000000000 +0200 | |
15 | +++ linux-2.6.27-SLE11_BRANCH-1-reiserfs_corruption/fs/reiserfs/inode.c 2009-06-24 14:39:44.000000000 +0200 | |
16 | @@ -2606,6 +2610,8 @@ static int reiserfs_write_begin(struct f | |
17 | if (ret) { | |
18 | unlock_page(page); | |
19 | page_cache_release(page); | |
20 | + /* Truncate allocated blocks */ | |
21 | + vmtruncate(inode, inode->i_size); | |
22 | } | |
23 | return ret; | |
24 | } | |
25 | @@ -2698,8 +2705,7 @@ static int reiserfs_write_end(struct fil | |
26 | ** transaction tracking stuff when the size changes. So, we have | |
27 | ** to do the i_size updates here. | |
28 | */ | |
29 | - pos += copied; | |
30 | - if (pos > inode->i_size) { | |
31 | + if (pos + copied > inode->i_size) { | |
32 | struct reiserfs_transaction_handle myth; | |
33 | reiserfs_write_lock(inode->i_sb); | |
34 | /* If the file have grown beyond the border where it | |
35 | @@ -2717,7 +2723,7 @@ static int reiserfs_write_end(struct fil | |
36 | goto journal_error; | |
37 | } | |
38 | reiserfs_update_inode_transaction(inode); | |
39 | - inode->i_size = pos; | |
40 | + inode->i_size = pos + copied; | |
41 | /* | |
42 | * this will just nest into our transaction. It's important | |
43 | * to use mark_inode_dirty so the inode gets pushed around on the | |
44 | @@ -2744,6 +2750,10 @@ static int reiserfs_write_end(struct fil | |
45 | out: | |
46 | unlock_page(page); | |
47 | page_cache_release(page); | |
48 | + | |
49 | + if (pos + len > inode->i_size) | |
50 | + vmtruncate(inode, inode->i_size); | |
51 | + | |
52 | return ret == 0 ? copied : ret; | |
53 | ||
54 | journal_error: |