Add cc: stable@vger.kernel.org tags
[ext4-patch-queue.git] / move-size-update-routines-to-helper-function
blobf5ed0c819be024960560a43c6b6671390ba9c9fa
1 ext4: move i_size,i_disksize update routines to helper function
3 From: Dmitry Monakhov <dmonakhov@openvz.org>
5 Cc: stable@vger.kernel.org # needed for bug fix patches
6 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
7 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
8 ---
9  fs/ext4/ext4.h    | 16 ++++++++++++++++
10  fs/ext4/extents.c | 17 ++++-------------
11  fs/ext4/inode.c   | 34 ++++++++--------------------------
12  3 files changed, 28 insertions(+), 39 deletions(-)
14 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
15 index 5b19760..0badae0 100644
16 --- a/fs/ext4/ext4.h
17 +++ b/fs/ext4/ext4.h
18 @@ -2454,6 +2454,22 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
19         up_write(&EXT4_I(inode)->i_data_sem);
20  }
22 +/* Update i_size, i_disksize. Requires i_mutex to avoid races with truncate */
23 +static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
25 +       int changed = 0;
27 +       if (newsize > inode->i_size) {
28 +               i_size_write(inode, newsize);
29 +               changed = 1;
30 +       }
31 +       if (newsize > EXT4_I(inode)->i_disksize) {
32 +               ext4_update_i_disksize(inode, newsize);
33 +               changed |= 2;
34 +       }
35 +       return changed;
38  struct ext4_group_info {
39         unsigned long   bb_state;
40         struct rb_root  bb_free_root;
41 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
42 index 76c2df3..f0e6934 100644
43 --- a/fs/ext4/extents.c
44 +++ b/fs/ext4/extents.c
45 @@ -4839,12 +4839,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46         }
48         inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
50         if (new_size) {
51 -               if (new_size > i_size_read(inode))
52 -                       i_size_write(inode, new_size);
53 -               if (new_size > EXT4_I(inode)->i_disksize)
54 -                       ext4_update_i_disksize(inode, new_size);
55 +               ext4_update_inode_size(inode, new_size);
56         } else {
57                 /*
58                 * Mark that we allocate beyond EOF so the subsequent truncate
59 @@ -4886,7 +4882,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
60         int ret = 0;
61         int flags;
62         ext4_lblk_t lblk;
63 -       struct timespec tv;
64         unsigned int blkbits = inode->i_blkbits;
66         /* Return error if mode is not supported */
67 @@ -4945,15 +4940,11 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
68         if (IS_ERR(handle))
69                 goto out;
71 -       tv = inode->i_ctime = ext4_current_time(inode);
72 +       inode->i_ctime = ext4_current_time(inode);
74         if (new_size) {
75 -               if (new_size > i_size_read(inode)) {
76 -                       i_size_write(inode, new_size);
77 -                       inode->i_mtime = tv;
78 -               }
79 -               if (new_size > EXT4_I(inode)->i_disksize)
80 -                       ext4_update_i_disksize(inode, new_size);
81 +               if (ext4_update_inode_size(inode, new_size) & 0x1)
82 +                       inode->i_mtime = inode->i_ctime;
83         } else {
84                 /*
85                 * Mark that we allocate beyond EOF so the subsequent truncate
86 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
87 index 367a60c..b1ddd93 100644
88 --- a/fs/ext4/inode.c
89 +++ b/fs/ext4/inode.c
90 @@ -1055,27 +1055,11 @@ static int ext4_write_end(struct file *file,
91         } else
92                 copied = block_write_end(file, mapping, pos,
93                                          len, copied, page, fsdata);
95         /*
96 -        * No need to use i_size_read() here, the i_size
97 -        * cannot change under us because we hole i_mutex.
98 -        *
99 -        * But it's important to update i_size while still holding page lock:
100 +        * it's important to update i_size while still holding page lock:
101          * page writeout could otherwise come in and zero beyond i_size.
102          */
103 -       if (pos + copied > inode->i_size) {
104 -               i_size_write(inode, pos + copied);
105 -               i_size_changed = 1;
106 -       }
108 -       if (pos + copied > EXT4_I(inode)->i_disksize) {
109 -               /* We need to mark inode dirty even if
110 -                * new_i_size is less that inode->i_size
111 -                * but greater than i_disksize. (hint delalloc)
112 -                */
113 -               ext4_update_i_disksize(inode, (pos + copied));
114 -               i_size_changed = 1;
115 -       }
116 +       i_size_changed = ext4_update_inode_size(inode, pos + copied);
117         unlock_page(page);
118         page_cache_release(page);
120 @@ -1123,7 +1107,7 @@ static int ext4_journalled_write_end(struct file *file,
121         int ret = 0, ret2;
122         int partial = 0;
123         unsigned from, to;
124 -       loff_t new_i_size;
125 +       int size_changed = 0;
127         trace_ext4_journalled_write_end(inode, pos, len, copied);
128         from = pos & (PAGE_CACHE_SIZE - 1);
129 @@ -1146,20 +1130,18 @@ static int ext4_journalled_write_end(struct file *file,
130                 if (!partial)
131                         SetPageUptodate(page);
132         }
133 -       new_i_size = pos + copied;
134 -       if (new_i_size > inode->i_size)
135 -               i_size_write(inode, pos+copied);
136 +       size_changed = ext4_update_inode_size(inode, pos + copied);
137         ext4_set_inode_state(inode, EXT4_STATE_JDATA);
138         EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
139 -       if (new_i_size > EXT4_I(inode)->i_disksize) {
140 -               ext4_update_i_disksize(inode, new_i_size);
141 +       unlock_page(page);
142 +       page_cache_release(page);
144 +       if (size_changed) {
145                 ret2 = ext4_mark_inode_dirty(handle, inode);
146                 if (!ret)
147                         ret = ret2;
148         }
150 -       unlock_page(page);
151 -       page_cache_release(page);
152         if (pos + len > inode->i_size && ext4_can_truncate(inode))
153                 /* if we have allocated more blocks and copied
154                  * less. We will have blocks allocated outside