aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorVladimir V. Saveliev <vs@namesys.com>2006-12-06 23:39:12 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:42 -0500
commitc55747682e938c57a9a859d3b26f2c4c83cea011 (patch)
tree5af319c0a61851b68be9cef30172808f6e8e77f0 /fs
parent301827acbe49d0ba7ec9770803970893ac9ded97 (diff)
[PATCH] reiserfs: do not add save links for O_DIRECT writes
We add a save link for O_DIRECT writes to protect the i_size against the crashes before we actually finish the I/O. If we hit an -ENOSPC in aops->prepare_write(), we would do a truncate() to release the blocks which might have got initialized. Now the truncate would add another save link for the same inode causing a reiserfs panic for having multiple save links for the same inode. Signed-off-by: Vladimir V. Saveliev <vs@namesys.com> Signed-off-by: Amit Arora <amitarora@in.ibm.com> Signed-off-by: Suzuki K P <suzuki@in.ibm.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Chris Mason <mason@suse.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/reiserfs/file.c54
1 files changed, 4 insertions, 50 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 970ecd9dbe69..373d862c3f87 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -406,6 +406,8 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl
406 we restart it. This will also free the path. */ 406 we restart it. This will also free the path. */
407 if (journal_transaction_should_end 407 if (journal_transaction_should_end
408 (th, th->t_blocks_allocated)) { 408 (th, th->t_blocks_allocated)) {
409 inode->i_size = cpu_key_k_offset(&key) +
410 (to_paste << inode->i_blkbits);
409 res = 411 res =
410 restart_transaction(th, inode, 412 restart_transaction(th, inode,
411 &path); 413 &path);
@@ -1310,56 +1312,8 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
1310 count = MAX_NON_LFS - (unsigned long)*ppos; 1312 count = MAX_NON_LFS - (unsigned long)*ppos;
1311 } 1313 }
1312 1314
1313 if (file->f_flags & O_DIRECT) { // Direct IO needs treatment 1315 if (file->f_flags & O_DIRECT)
1314 ssize_t result, after_file_end = 0; 1316 return do_sync_write(file, buf, count, ppos);
1315 if ((*ppos + count >= inode->i_size)
1316 || (file->f_flags & O_APPEND)) {
1317 /* If we are appending a file, we need to put this savelink in here.
1318 If we will crash while doing direct io, finish_unfinished will
1319 cut the garbage from the file end. */
1320 reiserfs_write_lock(inode->i_sb);
1321 err =
1322 journal_begin(&th, inode->i_sb,
1323 JOURNAL_PER_BALANCE_CNT);
1324 if (err) {
1325 reiserfs_write_unlock(inode->i_sb);
1326 return err;
1327 }
1328 reiserfs_update_inode_transaction(inode);
1329 add_save_link(&th, inode, 1 /* Truncate */ );
1330 after_file_end = 1;
1331 err =
1332 journal_end(&th, inode->i_sb,
1333 JOURNAL_PER_BALANCE_CNT);
1334 reiserfs_write_unlock(inode->i_sb);
1335 if (err)
1336 return err;
1337 }
1338 result = do_sync_write(file, buf, count, ppos);
1339
1340 if (after_file_end) { /* Now update i_size and remove the savelink */
1341 struct reiserfs_transaction_handle th;
1342 reiserfs_write_lock(inode->i_sb);
1343 err = journal_begin(&th, inode->i_sb, 1);
1344 if (err) {
1345 reiserfs_write_unlock(inode->i_sb);
1346 return err;
1347 }
1348 reiserfs_update_inode_transaction(inode);
1349 mark_inode_dirty(inode);
1350 err = journal_end(&th, inode->i_sb, 1);
1351 if (err) {
1352 reiserfs_write_unlock(inode->i_sb);
1353 return err;
1354 }
1355 err = remove_save_link(inode, 1 /* truncate */ );
1356 reiserfs_write_unlock(inode->i_sb);
1357 if (err)
1358 return err;
1359 }
1360
1361 return result;
1362 }
1363 1317
1364 if (unlikely((ssize_t) count < 0)) 1318 if (unlikely((ssize_t) count < 0))
1365 return -EINVAL; 1319 return -EINVAL;