diff options
-rw-r--r-- | fs/ocfs2/file.c | 42 |
1 files changed, 18 insertions, 24 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 78e245df5e32..fc53ff065364 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2106,7 +2106,7 @@ out: | |||
2106 | } | 2106 | } |
2107 | 2107 | ||
2108 | static int ocfs2_prepare_inode_for_write(struct file *file, | 2108 | static int ocfs2_prepare_inode_for_write(struct file *file, |
2109 | loff_t *ppos, | 2109 | loff_t pos, |
2110 | size_t count, | 2110 | size_t count, |
2111 | int appending, | 2111 | int appending, |
2112 | int *direct_io, | 2112 | int *direct_io, |
@@ -2115,7 +2115,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
2115 | int ret = 0, meta_level = 0; | 2115 | int ret = 0, meta_level = 0; |
2116 | struct dentry *dentry = file->f_path.dentry; | 2116 | struct dentry *dentry = file->f_path.dentry; |
2117 | struct inode *inode = dentry->d_inode; | 2117 | struct inode *inode = dentry->d_inode; |
2118 | loff_t saved_pos = 0, end; | 2118 | loff_t end; |
2119 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2119 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2120 | int full_coherency = !(osb->s_mount_opt & | 2120 | int full_coherency = !(osb->s_mount_opt & |
2121 | OCFS2_MOUNT_COHERENCY_BUFFERED); | 2121 | OCFS2_MOUNT_COHERENCY_BUFFERED); |
@@ -2155,23 +2155,16 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
2155 | } | 2155 | } |
2156 | } | 2156 | } |
2157 | 2157 | ||
2158 | /* work on a copy of ppos until we're sure that we won't have | 2158 | end = pos + count; |
2159 | * to recalculate it due to relocking. */ | ||
2160 | if (appending) | ||
2161 | saved_pos = i_size_read(inode); | ||
2162 | else | ||
2163 | saved_pos = *ppos; | ||
2164 | |||
2165 | end = saved_pos + count; | ||
2166 | 2159 | ||
2167 | ret = ocfs2_check_range_for_refcount(inode, saved_pos, count); | 2160 | ret = ocfs2_check_range_for_refcount(inode, pos, count); |
2168 | if (ret == 1) { | 2161 | if (ret == 1) { |
2169 | ocfs2_inode_unlock(inode, meta_level); | 2162 | ocfs2_inode_unlock(inode, meta_level); |
2170 | meta_level = -1; | 2163 | meta_level = -1; |
2171 | 2164 | ||
2172 | ret = ocfs2_prepare_inode_for_refcount(inode, | 2165 | ret = ocfs2_prepare_inode_for_refcount(inode, |
2173 | file, | 2166 | file, |
2174 | saved_pos, | 2167 | pos, |
2175 | count, | 2168 | count, |
2176 | &meta_level); | 2169 | &meta_level); |
2177 | if (has_refcount) | 2170 | if (has_refcount) |
@@ -2227,7 +2220,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
2227 | * caller will have to retake some cluster | 2220 | * caller will have to retake some cluster |
2228 | * locks and initiate the io as buffered. | 2221 | * locks and initiate the io as buffered. |
2229 | */ | 2222 | */ |
2230 | ret = ocfs2_check_range_for_holes(inode, saved_pos, count); | 2223 | ret = ocfs2_check_range_for_holes(inode, pos, count); |
2231 | if (ret == 1) { | 2224 | if (ret == 1) { |
2232 | /* | 2225 | /* |
2233 | * Fallback to old way if the feature bit is not set. | 2226 | * Fallback to old way if the feature bit is not set. |
@@ -2242,12 +2235,9 @@ static int ocfs2_prepare_inode_for_write(struct file *file, | |||
2242 | break; | 2235 | break; |
2243 | } | 2236 | } |
2244 | 2237 | ||
2245 | if (appending) | ||
2246 | *ppos = saved_pos; | ||
2247 | |||
2248 | out_unlock: | 2238 | out_unlock: |
2249 | trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, | 2239 | trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, |
2250 | saved_pos, appending, count, | 2240 | pos, appending, count, |
2251 | direct_io, has_refcount); | 2241 | direct_io, has_refcount); |
2252 | 2242 | ||
2253 | if (meta_level >= 0) | 2243 | if (meta_level >= 0) |
@@ -2263,7 +2253,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | |||
2263 | int ret, direct_io, appending, rw_level, have_alloc_sem = 0; | 2253 | int ret, direct_io, appending, rw_level, have_alloc_sem = 0; |
2264 | int can_do_direct, has_refcount = 0; | 2254 | int can_do_direct, has_refcount = 0; |
2265 | ssize_t written = 0; | 2255 | ssize_t written = 0; |
2266 | size_t count = iov_iter_count(from); | 2256 | size_t count = iov_iter_count(from), orig_count; |
2267 | loff_t old_size; | 2257 | loff_t old_size; |
2268 | u32 old_clusters; | 2258 | u32 old_clusters; |
2269 | struct file *file = iocb->ki_filp; | 2259 | struct file *file = iocb->ki_filp; |
@@ -2329,8 +2319,16 @@ relock: | |||
2329 | ocfs2_inode_unlock(inode, 1); | 2319 | ocfs2_inode_unlock(inode, 1); |
2330 | } | 2320 | } |
2331 | 2321 | ||
2322 | orig_count = count; | ||
2323 | ret = generic_write_checks(file, &iocb->ki_pos, &count); | ||
2324 | if (ret < 0) { | ||
2325 | mlog_errno(ret); | ||
2326 | goto out; | ||
2327 | } | ||
2328 | iov_iter_truncate(from, count); | ||
2329 | |||
2332 | can_do_direct = direct_io; | 2330 | can_do_direct = direct_io; |
2333 | ret = ocfs2_prepare_inode_for_write(file, &iocb->ki_pos, count, appending, | 2331 | ret = ocfs2_prepare_inode_for_write(file, iocb->ki_pos, count, appending, |
2334 | &can_do_direct, &has_refcount); | 2332 | &can_do_direct, &has_refcount); |
2335 | if (ret < 0) { | 2333 | if (ret < 0) { |
2336 | mlog_errno(ret); | 2334 | mlog_errno(ret); |
@@ -2351,6 +2349,7 @@ relock: | |||
2351 | rw_level = -1; | 2349 | rw_level = -1; |
2352 | 2350 | ||
2353 | direct_io = 0; | 2351 | direct_io = 0; |
2352 | iov_iter_reexpand(from, count = orig_count); | ||
2354 | goto relock; | 2353 | goto relock; |
2355 | } | 2354 | } |
2356 | 2355 | ||
@@ -2374,11 +2373,6 @@ relock: | |||
2374 | /* communicate with ocfs2_dio_end_io */ | 2373 | /* communicate with ocfs2_dio_end_io */ |
2375 | ocfs2_iocb_set_rw_locked(iocb, rw_level); | 2374 | ocfs2_iocb_set_rw_locked(iocb, rw_level); |
2376 | 2375 | ||
2377 | ret = generic_write_checks(file, &iocb->ki_pos, &count); | ||
2378 | if (ret) | ||
2379 | goto out_dio; | ||
2380 | |||
2381 | iov_iter_truncate(from, count); | ||
2382 | if (direct_io) { | 2376 | if (direct_io) { |
2383 | loff_t endbyte; | 2377 | loff_t endbyte; |
2384 | ssize_t written_buffered; | 2378 | ssize_t written_buffered; |