diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-02-16 14:46:50 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-04-26 18:02:20 -0400 |
commit | 60b11392f1a09433740bda3048202213daa27736 (patch) | |
tree | a8687fcb0ce62b130b732d663b54a984564d28b2 /fs/ocfs2/file.c | |
parent | 25baf2da1473d9dcde1a4c7b0ab26e7d67d9bf62 (diff) |
ocfs2: zero tail of sparse files on truncate
Since we don't zero on extend anymore, truncate needs to be fixed up to zero
the part of a file between i_size and and end of it's cluster. Otherwise a
subsequent extend could expose bad data.
This introduced a new helper, which can be used in ocfs2_write().
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 667e5a869bf5..5fd49ec169dc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -262,6 +262,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, | |||
262 | { | 262 | { |
263 | int status; | 263 | int status; |
264 | handle_t *handle; | 264 | handle_t *handle; |
265 | struct ocfs2_dinode *di; | ||
265 | 266 | ||
266 | mlog_entry_void(); | 267 | mlog_entry_void(); |
267 | 268 | ||
@@ -275,12 +276,39 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, | |||
275 | goto out; | 276 | goto out; |
276 | } | 277 | } |
277 | 278 | ||
278 | status = ocfs2_set_inode_size(handle, inode, fe_bh, new_i_size); | 279 | status = ocfs2_journal_access(handle, inode, fe_bh, |
280 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
281 | if (status < 0) { | ||
282 | mlog_errno(status); | ||
283 | goto out_commit; | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Do this before setting i_size. | ||
288 | */ | ||
289 | status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size); | ||
290 | if (status) { | ||
291 | mlog_errno(status); | ||
292 | goto out_commit; | ||
293 | } | ||
294 | |||
295 | i_size_write(inode, new_i_size); | ||
296 | inode->i_blocks = ocfs2_align_bytes_to_sectors(new_i_size); | ||
297 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
298 | |||
299 | di = (struct ocfs2_dinode *) fe_bh->b_data; | ||
300 | di->i_size = cpu_to_le64(new_i_size); | ||
301 | di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec); | ||
302 | di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); | ||
303 | |||
304 | status = ocfs2_journal_dirty(handle, fe_bh); | ||
279 | if (status < 0) | 305 | if (status < 0) |
280 | mlog_errno(status); | 306 | mlog_errno(status); |
281 | 307 | ||
308 | out_commit: | ||
282 | ocfs2_commit_trans(osb, handle); | 309 | ocfs2_commit_trans(osb, handle); |
283 | out: | 310 | out: |
311 | |||
284 | mlog_exit(status); | 312 | mlog_exit(status); |
285 | return status; | 313 | return status; |
286 | } | 314 | } |
@@ -343,7 +371,6 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
343 | mlog_errno(status); | 371 | mlog_errno(status); |
344 | goto bail; | 372 | goto bail; |
345 | } | 373 | } |
346 | ocfs2_data_unlock(inode, 1); | ||
347 | 374 | ||
348 | /* alright, we're going to need to do a full blown alloc size | 375 | /* alright, we're going to need to do a full blown alloc size |
349 | * change. Orphan the inode so that recovery can complete the | 376 | * change. Orphan the inode so that recovery can complete the |
@@ -352,22 +379,25 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
352 | status = ocfs2_orphan_for_truncate(osb, inode, di_bh, new_i_size); | 379 | status = ocfs2_orphan_for_truncate(osb, inode, di_bh, new_i_size); |
353 | if (status < 0) { | 380 | if (status < 0) { |
354 | mlog_errno(status); | 381 | mlog_errno(status); |
355 | goto bail; | 382 | goto bail_unlock_data; |
356 | } | 383 | } |
357 | 384 | ||
358 | status = ocfs2_prepare_truncate(osb, inode, di_bh, &tc); | 385 | status = ocfs2_prepare_truncate(osb, inode, di_bh, &tc); |
359 | if (status < 0) { | 386 | if (status < 0) { |
360 | mlog_errno(status); | 387 | mlog_errno(status); |
361 | goto bail; | 388 | goto bail_unlock_data; |
362 | } | 389 | } |
363 | 390 | ||
364 | status = ocfs2_commit_truncate(osb, inode, di_bh, tc); | 391 | status = ocfs2_commit_truncate(osb, inode, di_bh, tc); |
365 | if (status < 0) { | 392 | if (status < 0) { |
366 | mlog_errno(status); | 393 | mlog_errno(status); |
367 | goto bail; | 394 | goto bail_unlock_data; |
368 | } | 395 | } |
369 | 396 | ||
370 | /* TODO: orphan dir cleanup here. */ | 397 | /* TODO: orphan dir cleanup here. */ |
398 | bail_unlock_data: | ||
399 | ocfs2_data_unlock(inode, 1); | ||
400 | |||
371 | bail: | 401 | bail: |
372 | 402 | ||
373 | mlog_exit(status); | 403 | mlog_exit(status); |